Module: BatchKit::Encryption

Defined in:
lib/batch-kit/encryption/java_encryption.rb,
lib/batch-kit/encryption/ruby_encryption.rb

Overview

Performs password-based encryption (PBE) and decryption using the AES 128-bit cipher algorithm. Password-based encryption uses a password or passphrase as the shared secret key with which to encrypt/decrypt other text.

As with all key-based encryption schemes, the encrypted values are only as secure as the key used to encrypt them. If the key is accessible to a hacker, any values encrypted with the key can be decrypted, so the key should be stored separately from the encrypted values, and be kept as secure as possible.

Constant Summary collapse

KEY_ALGORITHM =

Use PBKDF2 with SHA-1 as the key hashing algorithm The NIST specifically names SHA1 as an acceptable hashing algorithm for PKBDF2

:pbkdf2_hmac_sha1
KEY_ITERATION_COUNT =

Iteration count; NIST recommends at least 1000 iterations

5000
KEY_DERIVED_LENGTH =

Length of the generated key in bits

128
CIPHER_ALGORITHM =

Algorithm to use for encryption

'AES-128-CBC'
SALT =
Note:

The same value must be used for the salt when converting a key

Salt; a random 8 bytes used to generate an encryption key from a key password / passphrase.

password/passphrase into an encryption key for both encryptionn and decryption.

[70, 211, 28, 57, 192, 6, 78, 163].pack("CCCCCCCC")

Class Method Summary collapse

Class Method Details

.base64_decode(str) ⇒ Array<byte>

Convert a base-64 encoded string to a byte array.

Parameters:

  • str (String)

    A base-64 encoded String.

Returns:

  • (Array<byte>)

    A String containing the decoded bytes.



151
152
153
# File 'lib/batch-kit/encryption/java_encryption.rb', line 151

def base64_decode(str)
    javax.xml.bind.DatatypeConverter.parseBase64Binary(str)
end

.base64_encode(bytes) ⇒ String

Convert a byte array to a base-64 encoded string representation.

Parameters:

  • bytes (String, Array<String>)

    A String or Java byte-array to be encoded.

Returns:

  • (String)

    A base-64 encoded String.



140
141
142
143
# File 'lib/batch-kit/encryption/java_encryption.rb', line 140

def base64_encode(bytes)
    bytes = bytes.to_java_bytes if bytes.is_a?(String)
    javax.xml.bind.DatatypeConverter.printBase64Binary(bytes)
end

.decipher(key, cipher_text, cipher_algorithm = CIPHER_ALGORITHM) ⇒ String

Decipher the supplited cipher_text, using key as the decipher key.

Parameters:

  • key (String)

    The key used for encryption.

  • cipher_text (String)

    A base-64 encoded cipher text string that is to be decrypted.

  • cipher_algorithm (String) (defaults to: CIPHER_ALGORITHM)

    The name of the cipher algorithm used to encrypt the clear_text.

Returns:

  • (String)

    The clear text that was encrypted.



120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/batch-kit/encryption/java_encryption.rb', line 120

def decipher(key, cipher_text, cipher_algorithm = CIPHER_ALGORITHM)
    cipher = Cipher.getInstance(cipher_algorithm)
    buffer_bytes = base64_decode(cipher_text)
    # Unpack IV and cipher bytes
    iv_bytes = Java::byte[KEY_DERIVED_LENGTH / 8].new
    cipher_bytes = Java::byte[buffer_bytes.length - KEY_DERIVED_LENGTH / 8].new
    buffer = java.nio.ByteBuffer.wrap(buffer_bytes)
    buffer.get(iv_bytes)
    buffer.get(cipher_bytes)
    cipher.init(Cipher::DECRYPT_MODE, key, IvParameterSpec.new(iv_bytes))
    String.from_java_bytes(cipher.doFinal(cipher_bytes))
end

.decrypt(key_text, cipher_text, salt = SALT) ⇒ String

Decrypt the supplied cipher_text, using key_text as the pass-phrase.

Parameters:

  • key_text (String)

    The clear-text pass-phrase to use as the key for decryption.

  • cipher_text (String)

    A base-64 encoded cipher text string that is to be decrypted.

  • salt (Array<Byte>) (defaults to: SALT)

    An 8-byte array of random values to use as the salt. Like the key_text, it is imperative that the same value is used for the salt when decrypting a previously encrypted value.

Returns:

  • (String)

    The clear text that was encrypted.



105
106
107
108
# File 'lib/batch-kit/encryption/java_encryption.rb', line 105

def decrypt(key_text, cipher_text, salt = SALT)
    key = generate_key(key_text, salt)
    decipher(key, cipher_text)
end

.encipher(key, clear_text, cipher_algorithm = CIPHER_ALGORITHM) ⇒ String

Encipher the supplied clear_text, using key as the encryption key.

Note: this method is possibly less secure than #encrypt, since it uses the actual key in the enciphering, rather than an SHA1 hash of the key.

Parameters:

  • key (String)

    The key to use for encryption.

  • clear_text (String)

    The cleartext string to be encrypted.

  • cipher_algorithm (String) (defaults to: CIPHER_ALGORITHM)

    The name of the cipher algorithm to use when encrypting the clear_text.

Returns:

  • (String)

    A base-64 encoded string representing the encrypted clear_text value.



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/batch-kit/encryption/java_encryption.rb', line 79

def encipher(key, clear_text, cipher_algorithm = CIPHER_ALGORITHM)
    cipher = Cipher.getInstance(cipher_algorithm)
    cipher.init(Cipher::ENCRYPT_MODE, key)
    params = cipher.getParameters()
    iv = params.getParameterSpec(IvParameterSpec.java_class).getIV()
    cipher_bytes = cipher.doFinal(clear_text.to_java_bytes)
    # Combine IV and cipher bytes, and base-64 encode
    buffer_bytes = Java::byte[KEY_DERIVED_LENGTH / 8 + cipher_bytes.length].new
    buffer = java.nio.ByteBuffer.wrap(buffer_bytes)
    buffer.put(iv)
    buffer.put(cipher_bytes)
    base64_encode(buffer_bytes)
end

.encrypt(key_text, clear_text, salt = SALT) ⇒ String

Encrypt the supplied clear_text, using key_text as the pass-phrase.

Parameters:

  • key_text (String)

    The clear-text pass-phrase to use as the key for encryption.

  • clear_text (String)

    The cleartext string to be encrypted.

  • salt (Array<Byte>) (defaults to: SALT)

    An 8-byte array of random values to use as the salt.

Returns:

  • (String)

    A base-64 encoded string representing the encrypted clear_text value.



61
62
63
64
# File 'lib/batch-kit/encryption/java_encryption.rb', line 61

def encrypt(key_text, clear_text, salt = SALT)
    key = generate_key(key_text, salt)
    encipher(key, clear_text)
end

.generate_key(key_text, salt) ⇒ SecretKey

Generates the key to be used for encryption/decryption, based on key_text and salt.

Parameters:

  • key_text (String)

    A clear-text password or pass phrase that is to be used to derive the encryption key.

  • salt (String)

    A String containing a random salt.

Returns:

  • (SecretKey)

    A key that can be used for encryption/decryption.



167
168
169
170
171
172
173
# File 'lib/batch-kit/encryption/java_encryption.rb', line 167

def generate_key(key_text, salt)
    factory = SecretKeyFactory.getInstance(KEY_ALGORITHM)
    key_spec = PBEKeySpec.new(key_text.to_s.to_java.toCharArray(), salt,
                              KEY_ITERATION_COUNT, KEY_DERIVED_LENGTH)
    key = factory.generateSecret(key_spec)
    SecretKeySpec.new(key.getEncoded(), CIPHER_ALGORITHM.split('/').first)
end

.generate_master_keyString

Generate a random master key that can be used to encrypt/decrypt other sensitive data such as passwords. The master key must be stored some place separate from the values it is used to encrypt.

Returns:

  • (String)

    A random string of text that can be used as a master key for encrypting/decrypting other values.



46
47
48
# File 'lib/batch-kit/encryption/java_encryption.rb', line 46

def generate_master_key()
    java.util.UUID.randomUUID().toString()
end