Class: McAPI::Encryption::Crypto

Inherits:
Object
  • Object
show all
Defined in:
lib/mcapi/encryption/crypto/crypto.rb

Overview

Crypto class provide RSA/AES encrypt/decrypt methods

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ Crypto

Create a new instance with the provided config

Parameters:

  • config (Hash)

    configuration object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/mcapi/encryption/crypto/crypto.rb', line 20

def initialize(config)
  valid_config?(config)
  @encoding = config['dataEncoding']
  @cert = OpenSSL::X509::Certificate.new(IO.binread(config['encryptionCertificate']))
  if config['privateKey']
    @private_key = OpenSSL::PKey.read(IO.binread(config['privateKey']))
  elsif config['keyStore']
    @private_key = OpenSSL::PKCS12.new(IO.binread(config['keyStore']), config['keyStorePassword']).key
  end
  @oaep_hashing_alg = config['oaepPaddingDigestAlgorithm']
  @encrypted_value_field_name = config['encryptedValueFieldName']
  @encrypted_key_field_name = config['encryptedKeyFieldName']
  @public_key_fingerprint = compute_public_fingerprint(config['publicKeyFingerprintType'])
  @public_key_fingerprint_field_name = config['publicKeyFingerprintFieldName']
  @oaep_hashing_alg_field_name = config['oaepHashingAlgorithmFieldName']
end

Instance Method Details

#decrypt_data(encrypted_data, iv, encrypted_key, oaep_hashing_alg) ⇒ String

Perform data decryption

Parameters:

  • encrypted_data (String)

    encrypted data to decrypt

  • iv (String)

    Initialization vector to use to create the Decipher

  • encrypted_key (String)

    Encrypted key to use to decrypt the data (the key is the decrypted using the provided PrivateKey)

  • oaep_hashing_alg (String)

    OAEP Algorithm to use

Returns:

  • (String)

    Decrypted JSON object



110
111
112
113
114
115
116
117
118
# File 'lib/mcapi/encryption/crypto/crypto.rb', line 110

def decrypt_data(encrypted_data, iv, encrypted_key, oaep_hashing_alg)
  md = Utils.create_message_digest(oaep_hashing_alg)
  decrypted_key = @private_key.private_decrypt_oaep(Utils.decode(encrypted_key, @encoding), '', md, md)
  aes = OpenSSL::Cipher::AES.new(decrypted_key.size * 8, :CBC)
  aes.decrypt
  aes.key = decrypted_key
  aes.iv = Utils.decode(iv, @encoding)
  aes.update(Utils.decode(encrypted_data, @encoding)) + aes.final
end

#encrypt_data(data:, iv: nil, secret_key: nil, encryption_params: nil, encoding: nil) ⇒ String

Perform data encryption: If iv, secret_key, encryption_params and encoding are not provided, randoms will be generated.

Parameters:

  • data (String)

    json string to encrypt

  • (optional) (String, nil)

    iv Initialization vector to use to create the cipher, if not provided generate a random one

  • (optional) (String, nil)

    encryption_params encryption parameters

  • encoding (String) (defaults to: nil)

    encoding to use for the encrypted bytes (hex or base64)

Returns:

  • (String)

    encrypted data



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/mcapi/encryption/crypto/crypto.rb', line 79

def encrypt_data(data:, iv: nil, secret_key: nil, encryption_params: nil, encoding: nil)
  encoding ||= @encoding
  encryption_params ||= new_encryption_params(iv, secret_key)
  # Create Symmetric Cipher: AES 128-bit
  aes = OpenSSL::Cipher::AES.new(128, :CBC)
  # Initialize for encryption mode
  aes.encrypt
  aes.iv = encryption_params[:iv]
  aes.key = encryption_params[:secretKey]
  encrypted = aes.update(data) + aes.final
  data = {
      @encrypted_value_field_name => Utils.encode(encrypted, encoding),
      'iv' => Utils.encode(encryption_params[:iv], encoding)
  }
  data[@encrypted_key_field_name] = Utils.encode(encryption_params[:encryptedKey], encoding) if @encrypted_key_field_name
  data[@public_key_fingerprint_field_name] = @public_key_fingerprint if @public_key_fingerprint
  data[@oaep_hashing_alg_field_name] = @oaep_hashing_alg.sub('-', '') if @oaep_hashing_alg_field_name
  data
end

#new_encryption_params(iv = nil, secret_key = nil) ⇒ Hash

Generate encryption parameters.

Parameters:

  • iv (String, nil) (defaults to: nil)

    IV to use instead to generate a random IV

  • secret_key (String, nil) (defaults to: nil)

    Secret Key to use instead to generate a random key

Returns:

  • (Hash)

    hash with the generated encryption parameters



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/mcapi/encryption/crypto/crypto.rb', line 45

def new_encryption_params(iv = nil, secret_key = nil)
  # Generate a secret key (should be 128 (or 256) bits)
  secret_key ||= OpenSSL::Random.random_bytes(16)
  # Generate a random initialization vector (IV)
  iv ||= OpenSSL::Random.random_bytes(16)
  md = Utils.create_message_digest(@oaep_hashing_alg)
  # Encrypt secret key with issuer key
  encrypted_key = @cert.public_key.public_encrypt_oaep(secret_key, '', md, md)

  {
      iv: iv,
      secretKey: secret_key,
      encryptedKey: encrypted_key,
      oaepHashingAlgorithm: @oaep_hashing_alg,
      publicKeyFingerprint: @public_key_fingerprint,
      encoded: {
          iv: Utils.encode(iv, @encoding),
          secretKey: Utils.encode(secret_key, @encoding),
          encryptedKey: Utils.encode(encrypted_key, @encoding)
      }
  }
end