Class: Virgil::SDK::Cryptography::VirgilCrypto

Inherits:
Object
  • Object
show all
Includes:
Crypto
Defined in:
lib/virgil/sdk/cryptography/virgil_crypto.rb

Overview

Wrapper for cryptographic operations.

Class provides a cryptographic operations in applications, such as hashing, signature generation and verification, and encryption and decryption

Defined Under Namespace

Classes: SignatureIsNotValid

Constant Summary collapse

CUSTOM_PARAM_KEY_SIGNATURE =
Crypto::Bytes.from_string(
  'VIRGIL-DATA-SIGNATURE'
)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key_pair_type = Keys::KeyPairType::Default) ⇒ VirgilCrypto

Returns a new instance of VirgilCrypto.



47
48
49
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 47

def initialize(key_pair_type=Keys::KeyPairType::Default)
  @key_pair_type = key_pair_type
end

Instance Attribute Details

#key_pair_typeObject

Returns the value of attribute key_pair_type.



45
46
47
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 45

def key_pair_type
  @key_pair_type
end

Instance Method Details

#calculate_fingerprint(bytes) ⇒ Object

Calculates the fingerprint.

Args:

bytes: data bytes for fingerprint calculation.

Returns:

Fingerprint of the source data.


377
378
379
380
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 377

def calculate_fingerprint(bytes)
  hash_bytes = self.compute_hash(bytes, Hashes::HashAlgorithm::SHA256)
  Hashes::Fingerprint.new(hash_bytes)
end

#compute_hash(bytes, algorithm) ⇒ Object

Computes the hash of specified data.

Args:

bytes: data bytes for fingerprint calculation.
algorithm: hashing algorithm.
  The possible values can be found in HashAlgorithm enum.

Returns:

Hash bytes.


391
392
393
394
395
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 391

def compute_hash(bytes, algorithm)
  native_algorithm = Hashes::HashAlgorithm.convert_to_native(algorithm)
  native_hasher = Crypto::Native::VirgilHash.new(native_algorithm)
  wrap_bytes(native_hasher.hash(bytes))
end

#compute_public_key_hash(public_key) ⇒ Object

Computes the hash of specified public key using SHA256 algorithm.

Args:

public_key: public key for hashing.

Returns:

Hash bytes.


404
405
406
407
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 404

def compute_public_key_hash(public_key)
  public_key_der = Crypto::Native::VirgilKeyPair.public_key_to_der(public_key)
  self.compute_hash(public_key_der, Hashes::HashAlgorithm::SHA256)
end

#decrypt(cipher_bytes, private_key) ⇒ Object

Decrypts the specified bytes using Private key.

Args:

bytes: encrypted bytes bytes for decryption.
private_key: private key for decryption.

Returns:

Decrypted bytes bytes.


218
219
220
221
222
223
224
225
226
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 218

def decrypt(cipher_bytes, private_key)
  cipher = Crypto::Native::VirgilCipher.new
  decrypted_bytes = cipher.decrypt_with_key(
    cipher_bytes,
    private_key.receiver_id,
    private_key.value
  )
  wrap_bytes(decrypted_bytes)
end

#decrypt_stream(input_stream, output_stream, private_key) ⇒ Object

Decrypts the specified stream using Private key.

Args:

input_stream: readable stream containing input data.
output_stream: writable stream for output.
private_key: private key for decryption.


329
330
331
332
333
334
335
336
337
338
339
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 329

def decrypt_stream(input_stream, output_stream, private_key)
  cipher = Crypto::Native::VirgilChunkCipher.new
  source = Crypto::VirgilStreamDataSource.new(input_stream)
  sink = Crypto::VirgilStreamDataSink.new(output_stream)
  cipher.decrypt_with_key(
    source,
    sink,
    private_key.receiver_id,
    private_key.value
  )
end

#decrypt_then_verify(bytes, private_key, public_key) ⇒ Object

Decrypts and verifies the data.

Args:

bytes: encrypted data bytes.
private_key: private key for decryption.
public_key: public key for verification.

Returns:

Decrypted data bytes.

Raises:

SignatureIsNotValid: if signature is not verified.


265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 265

def decrypt_then_verify(bytes, private_key, public_key)
  cipher = Crypto::Native::VirgilCipher.new
  decrypted_bytes = cipher.decrypt_with_key(
    bytes,
    private_key.receiver_id,
    private_key.value
  )
  signature = cipher.custom_params.get_data(CUSTOM_PARAM_KEY_SIGNATURE)
  is_valid = self.verify(decrypted_bytes, signature, public_key)
  unless is_valid
    raise SignatureIsNotValid.new
  end
  wrap_bytes(decrypted_bytes)
end

#encrypt(bytes, *recipients) ⇒ Object

Encrypts the specified bytes using recipients Public keys.

Args:

bytes: raw data bytes for encryption.
recipients: list of recipients' public keys.

Returns:

Encrypted bytes bytes.


202
203
204
205
206
207
208
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 202

def encrypt(bytes, *recipients)
  cipher = Crypto::Native::VirgilCipher.new
  recipients.each do |public_key|
    cipher.add_key_recipient(public_key.receiver_id, public_key.value)
  end
  wrap_bytes(cipher.encrypt(bytes))
end

#encrypt_stream(input_stream, output_stream, *recipients) ⇒ Object

Encrypts the specified stream using recipients Public keys.

Args:

input_stream: readable stream containing input bytes.
output_stream: writable stream for output.
recipients: list of recipients' public keys.


313
314
315
316
317
318
319
320
321
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 313

def encrypt_stream(input_stream, output_stream, *recipients)
  cipher = Crypto::Native::VirgilChunkCipher.new
  recipients.each do |public_key|
    cipher.add_key_recipient(public_key.receiver_id, public_key.value)
  end
  source = Crypto::VirgilStreamDataSource.new(input_stream)
  sink = Crypto::VirgilStreamDataSink.new(output_stream)
  wrap_bytes(cipher.encrypt(source, sink))
end

#export_private_key(private_key, password = nil) ⇒ Object

Exports the Private key into material representation.

Args:

private_key: private key for export.
password: private key password, nil by default.

Returns:

Key material representation bytes.


141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 141

def export_private_key(private_key, password=nil)
  unless password
    return Crypto::Native::VirgilKeyPair.private_key_to_der(
      private_key.value
    )
  end

  password_bytes = Crypto::Bytes.from_string(password)
  private_key_bytes = Crypto::Native::VirgilKeyPair.encrypt_private_key(
    private_key.value,
    password_bytes
  )
  wrap_bytes(
    Crypto::Native::VirgilKeyPair.private_key_to_der(
      private_key_bytes,
      password_bytes
    )
  )
end

#export_public_key(public_key) ⇒ Object

Exports the Public key into material representation.

Args:

public_key: public key for export.

Returns:

Key material representation bytes.


168
169
170
171
172
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 168

def export_public_key(public_key)
  wrap_bytes(
    Crypto::Native::VirgilKeyPair.public_key_to_der(public_key.value)
  )
end

#extract_public_key(private_key) ⇒ Object

Extracts the Public key from Private key.

Args:

private_key: source private key for extraction.

Returns:

Exported public key.


181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 181

def extract_public_key(private_key)
  public_key_bytes = Crypto::Native::VirgilKeyPair.extract_public_key(
    private_key.value,
    []
  )
  Keys::PublicKey.new(
    private_key.receiver_id,
    wrap_bytes(
      Crypto::Native::VirgilKeyPair.public_key_to_der(public_key_bytes)
    )
  )
end

#generate_keys(keys_type = @key_pair_type) ⇒ Object

Generates asymmetric key pair that is comprised of both public and private keys by specified type. Args:

key_pair_type: type of the generated keys.
  The possible values can be found in KeyPairType enum.

Returns:

Generated key pair.


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 68

def generate_keys(keys_type=@key_pair_type)
  native_type = Keys::KeyPairType.convert_to_native(keys_type)
  native_key_pair = Crypto::Native::VirgilKeyPair.generate(native_type)
  key_pair_id = self.compute_public_key_hash(native_key_pair.public_key)
  private_key = Keys::PrivateKey.new(
    key_pair_id,
    wrap_bytes(
      Crypto::Native::VirgilKeyPair.private_key_to_der(
        native_key_pair.private_key
      )
    )
  )
  public_key = Keys::PublicKey.new(
    key_pair_id,
    wrap_bytes(
      Crypto::Native::VirgilKeyPair.public_key_to_der(
        native_key_pair.public_key
      )
    )
  )
  return Keys::KeyPair.new(private_key, public_key)
end

#import_private_key(key_bytes, password = nil) ⇒ Object

Imports the Private key from material representation.

Args:

key_bytes: key material representation bytes.
password: private key password, nil by default.

Returns:

Imported private key.


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 99

def import_private_key(key_bytes, password=nil)
  decrypted_private_key = if !password
    Crypto::Native::VirgilKeyPair.private_key_to_der(key_bytes)
  else
    Crypto::Native::VirgilKeyPair.decrypt_private_key(
      key_bytes,
      Crypto::Bytes.from_string(password)
    )
  end

  public_key_bytes = Crypto::Native::VirgilKeyPair.extract_public_key(
    decrypted_private_key, []
  )
  key_pair_id = self.compute_public_key_hash(public_key_bytes)
  private_key_bytes = Crypto::Native::VirgilKeyPair.private_key_to_der(
    decrypted_private_key
  )
  return Keys::PrivateKey.new(key_pair_id, wrap_bytes(private_key_bytes))
end

#import_public_key(key_bytes) ⇒ Object

Imports the Public key from material representation.

Args:

key_bytes: key material representation bytes.

Returns:

Imported public key.


126
127
128
129
130
131
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 126

def import_public_key(key_bytes)
  key_pair_id = self.compute_public_key_hash(key_bytes)
  public_key_bytes =
    Crypto::Native::VirgilKeyPair.public_key_to_der(key_bytes)
  Keys::PublicKey.new(key_pair_id, wrap_bytes(public_key_bytes))
end

#sign(bytes, private_key) ⇒ Object

Signs the specified data using Private key.

Args:

bytes: raw data bytes for signing.
private_key: private key for signing.

Returns:

Signature data.


288
289
290
291
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 288

def sign(bytes, private_key)
  signer = Crypto::Native::VirgilSigner.new
  wrap_bytes(signer.sign(bytes, private_key.value))
end

#sign_stream(input_stream, private_key) ⇒ Object

Signs the specified stream using Private key.

Args:

input_stream: readable stream containing input data.
private_key: private key for signing.

Returns:

Signature bytes.


349
350
351
352
353
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 349

def sign_stream(input_stream, private_key)
  signer = Crypto::Native::VirgilStreamSigner.new
  source = Crypto::VirgilStreamDataSource.new(input_stream)
  wrap_bytes(signer.sign(source, private_key.value))
end

#sign_then_encrypt(bytes, private_key, *recipients) ⇒ Object

Signs and encrypts the data.

Args:

bytes: data bytes for signing and encryption.
private_key: private key to sign the data.
recipients: list of recipients' public keys.
  Used for data encryption.

Returns:

Signed and encrypted data bytes.


238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 238

def sign_then_encrypt(bytes, private_key, *recipients)
  signer = Crypto::Native::VirgilSigner.new
  signature = signer.sign(bytes, private_key.value)
  cipher = Crypto::Native::VirgilCipher.new
  custom_bytes = cipher.custom_params
  custom_bytes.set_data(
    CUSTOM_PARAM_KEY_SIGNATURE,
    signature
  )
  recipients.each do |public_key|
    cipher.add_key_recipient(public_key.receiver_id, public_key.value)
  end
  wrap_bytes(cipher.encrypt(bytes))
end

#verify(bytes, signature, signer_public_key) ⇒ Object

Verifies the specified signature using original data and signer’s public key.

Args:

bytes: original data bytes for verification.
signature: signature bytes for verification.
signer_public_key: signer public key for verification.

Returns:

True if signature is valid, False otherwise.


302
303
304
305
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 302

def verify(bytes, signature, signer_public_key)
  signer = Crypto::Native::VirgilSigner.new
  signer.verify(bytes, signature, signer_public_key.value)
end

#verify_stream(input_stream, signature, signer_public_key) ⇒ Object

Verifies the specified signature using original stream and signer’s Public key.

Args:

input_stream: readable stream containing input data.
signature: signature bytes for verification.
signer_public_key: signer public key for verification.

Returns:

True if signature is valid, False otherwise.


364
365
366
367
368
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 364

def verify_stream(input_stream, signature, signer_public_key)
  signer = Crypto::Native::VirgilStreamSigner.new
  source = Crypto::VirgilStreamDataSource.new(input_stream)
  signer.verify(source, signature, signer_public_key.value)
end