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'
)
CUSTOM_PARAM_KEY_SIGNER_ID =
Crypto::Bytes.from_string(
    'VIRGIL-DATA-SIGNER-ID'
)

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) ⇒ Hashes::Fingerprint

Calculates the fingerprint.

Examples:

# The default Fingerprint algorithm is SHA-256.
crypto = Virgil::SDK::Cryptography::VirgilCrypto.new
fingerprint = crypto.calculate_fingerprint(content_bytes)

Parameters:

  • bytes (Crypto::Bytes)

    data bytes for fingerprint calculation.

Returns:



429
430
431
432
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 429

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

#compute_hash(bytes, algorithm) ⇒ Crypto::Bytes

Computes the hash of specified data.

Parameters:

  • bytes (Crypto::Bytes)

    data bytes for fingerprint calculation.

  • algorithm (Hashes::HashAlgorithm)

    hashing algorithm. The possible values can be found in HashAlgorithm enum.

Returns:

  • (Crypto::Bytes)

    Hash bytes.



439
440
441
442
443
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 439

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) ⇒ Crypto::Bytes

Computes the hash of specified public key using SHA256 algorithm.

Parameters:

Returns:

  • (Crypto::Bytes)

    Hash bytes.



448
449
450
451
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 448

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) ⇒ Crypto::Bytes

Decrypts the specified bytes using Private key.

Examples:

# You can decrypt data using your private key
crypto = Virgil::SDK::Cryptography::VirgilCrypto.new
alice_keys = crypto.generate_keys
plain_data = crypto.decrypt(cipher_data, alice_keys.private_key)

Parameters:

  • cipher_bytes (Crypto::Bytes)

    encrypted data bytes for decryption.

  • private_key (Keys::PrivateKey)

    private key for decryption.

Returns:

  • (Crypto::Bytes)

    Decrypted data bytes.

See Also:



224
225
226
227
228
229
230
231
232
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 224

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.

Examples:

crypto = Virgil::SDK::Cryptography::VirgilCrypto.new
File.open("[YOUR_CIPHER_FILE_PATH_HERE]", "r") do |cipher_stream|
  File.open("[YOUR_DECRYPTED_FILE_PATH_HERE]", "w") do |decrypted_stream|
    alice_private_key = crypto.import_private_key(exported_private_key)
    crypto.decrypt_stream(cipher_stream, decrypted_stream, alice_private_key)
  end
end

Parameters:

  • input_stream (IO)

    readable stream containing encrypted data.

  • output_stream (IO)

    writable stream for output.

  • private_key (Keys::PrivateKey)

    private key for decryption.

See Also:



389
390
391
392
393
394
395
396
397
398
399
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 389

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_keys) ⇒ Crypto::Bytes

Decrypts and verifies the data.

Examples:

crypto = Virgil::SDK::Cryptography::VirgilCrypto.new

alice = crypto.generate_keys
bob = crypto.generate_keys

decrypted_data = crypto.decrypt_then_verify(
  cipher_data,
  bob.private_key,
  alice.public_key
)

Parameters:

  • bytes (Crypto::Bytes)

    encrypted data bytes.

  • private_key (Keys::PrivateKey)

    private key for decryption.

  • *public_keys (Array<Keys::PublicKey>)

    a list of public keys for verification, which can contain signer's public key.

Returns:

  • (Crypto::Bytes)

    Decrypted data bytes.

Raises:

See Also:



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 294

def decrypt_then_verify(bytes, private_key, *public_keys)
  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)

  signer_public_key = public_keys.first
  if public_keys.count > 1
    signer_id = cipher.custom_params.get_data(CUSTOM_PARAM_KEY_SIGNER_ID)

    signer_public_key = public_keys.find{|public_key| public_key.receiver_id == signer_id}

  end

  is_valid = self.verify(decrypted_bytes, signature, signer_public_key)
  unless is_valid
    raise SignatureIsNotValid.new
  end
  wrap_bytes(decrypted_bytes)
end

#encrypt(bytes, *recipients) ⇒ Crypto::Bytes

Encrypts the specified bytes using recipients Public keys.

Examples:

# Data encryption using ECIES scheme with AES-GCM.
# There can be more than one recipient.
crypto = Virgil::SDK::Cryptography::VirgilCrypto.new
alice_keys = crypto.generate_keys
plain_data = Virgil::Crypto::Bytes.from_string("Hello Bob!")
cipher_data = crypto.encrypt(plain_data, alice_keys.public_key)

Parameters:

  • bytes (Virgil::Crypto::Bytes)

    raw data bytes for encryption.

  • *recipients (Array<Keys::PublicKey>)

    list of recipients' public keys.

Returns:

  • (Crypto::Bytes)

    Encrypted bytes.

See Also:



205
206
207
208
209
210
211
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 205

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) ⇒ Crypto::Bytes

Encrypts the specified stream using recipients Public keys.

Examples:

crypto = Virgil::SDK::Cryptography::VirgilCrypto.new
alice_keys = crypto.generate_keys()
File.open("[YOUR_FILE_PATH_HERE]", "r") do |input_stream|
  File.open("[YOUR_CIPHER_FILE_PATH_HERE]", "w") do |cipher_stream|
    crypto.encrypt_stream(input_stream, cipher_stream, alice_keys.public_key)
  end
end

Parameters:

  • input_stream (IO)

    readable stream containing input bytes.

  • output_stream (IO)

    writable stream for output.

  • *recipients (Array<Keys::PublicKey>)

    list of recipients' public keys.

Returns:

  • (Crypto::Bytes)

    encrypted bytes.



365
366
367
368
369
370
371
372
373
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 365

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)
  cipher.encrypt(source, sink)
end

#export_private_key(private_key, password = nil) ⇒ Crypto::Bytes

Exports the Private key into material representation.

Examples:

crypto = Virgil::SDK::Cryptography::VirgilCrypto.new
alice_keys = crypto.generate_keys
exported_private_key = crypto.export_private_key(alice_keys.private_key)

Parameters:

  • private_key (Keys::PrivateKey)

    private key for export.

  • password (String) (defaults to: nil)

    private key password, nil by default.

Returns:

  • (Crypto::Bytes)

    Private key material representation bytes.



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

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) ⇒ Crypto::Bytes

Exports the Public key into material representation.

Examples:

crypto = Virgil::SDK::Cryptography::VirgilCrypto.new
alice_keys = crypto.generate_keys
exported_public_key = crypto.export_public_key(alice_keys.public_key)

Parameters:

Returns:

  • (Crypto::Bytes)

    Key material representation bytes.



171
172
173
174
175
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 171

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

#extract_public_key(private_key) ⇒ Keys::PublicKey

Extracts the Public key from Private key.

Parameters:

Returns:



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

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) ⇒ Keys::KeyPair

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

Examples:

crypto = Virgil::SDK::Cryptography::VirgilCrypto.new
alice_keys = crypto.generate_keys

Parameters:

  • keys_type (Symbol) (defaults to: @key_pair_type)

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

Returns:



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 73

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) ⇒ Keys::PrivateKey

Imports the Private key from material representation.

Examples:

private_key = crypto.import_private_key(exported_private_key)

Parameters:

  • key_bytes (Crypto::Bytes)

    private key material representation bytes.

  • password (String) (defaults to: nil)

    private key password, nil by default.

Returns:

See Also:



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 103

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) ⇒ Keys::PublicKey

Imports the Public key from material representation.

Examples:

public_key = crypto.import_public_key(exported_public_key)

Parameters:

  • key_bytes (Crypto::Bytes)

    public key material representation bytes.

Returns:

See Also:



129
130
131
132
133
134
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 129

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) ⇒ Crypto::Bytes

Signs the specified data using Private key.

Examples:

Sign the SHA-384 fingerprint of bytes using your private key.

crypto = Virgil::SDK::Cryptography::VirgilCrypto.new
alice_keys = crypto.generate_keys()
# The data to be signed with alice's Private key
data = Virgil::Crypto::Bytes.from_string("Hello Bob, How are you?")
signature = crypto.sign(data, alice.private_key)

Parameters:

  • bytes (Crypto::Bytes)

    raw data bytes for signing.

  • private_key (Keys::PrivateKey)

    private key for signing.

Returns:

  • (Crypto::Bytes)

    Signature data.

See Also:



330
331
332
333
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 330

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) ⇒ Crypto::Bytes

Signs the specified stream using Private key.

Parameters:

  • input_stream (IO)

    readable stream containing input data.

  • private_key (Keys::PrivateKey)

    private key for signing.

Returns:

  • (Crypto::Bytes)

    Signature bytes.



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

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) ⇒ Crypto::Bytes

Signs and encrypts the data.

Examples:

crypto = Virgil::SDK::Cryptography::VirgilCrypto.new

alice = crypto.generate_keys
bob = crypto.generate_keys

# The data to be signed with alice's Private key
data = Virgil::Crypto::Bytes.from_string("Hello Bob, How are you?")
cipher_data = crypto.sign_then_encrypt(
  data,
  alice.private_key,
  bob.public_key
)

Parameters:

  • bytes (Crypto::Bytes)

    data bytes for signing and encryption.

  • private_key (Keys::PrivateKey)

    private key to sign the data.

  • *recipients (Array<Keys::PublicKey>)

    list of recipients' public keys used for data encryption.

Returns:

  • (Crypto::Bytes)

    Signed and encrypted data bytes.



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 253

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
  )

  public_key = extract_public_key(private_key)
  custom_bytes.set_data(
      CUSTOM_PARAM_KEY_SIGNER_ID,
      wrap_bytes(public_key.receiver_id)
  )

  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) ⇒ Boolean

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

Examples:

Verify the signature of the SHA-384 fingerprint of bytes using Public key.

crypto = Virgil::SDK::Cryptography::VirgilCrypto.new
alice_keys = crypto.generate_keys()
data = Virgil::Crypto::Bytes.from_string("Hello Bob, How are you?")
is_valid = crypto.verify(data, signature, alice.public_key)

Parameters:

  • bytes (Crypto::Bytes)

    original data bytes for verification.

  • signature (Crypto::Bytes)

    signature bytes for verification.

  • signer_public_key (Keys::PublicKey)

    signer public key for verification.

Returns:

  • (Boolean)

    True if signature is valid, False otherwise.

See Also:



347
348
349
350
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 347

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) ⇒ Boolean

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

Parameters:

  • input_stream (IO)

    readable stream containing input data.

  • signature (Crypto::Bytes)

    signature bytes for verification.

  • signer_public_key (Keys::PublicKey)

    signer public key for verification.

Returns:

  • (Boolean)

    True if signature is valid, False otherwise.



416
417
418
419
420
# File 'lib/virgil/sdk/cryptography/virgil_crypto.rb', line 416

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