module BatchKit::Encryption

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.

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.

Constants

CIPHER_ALGORITHM

Algorithm to use for encryption

KEY_ALGORITHM

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

KEY_DERIVED_LENGTH

Length of the generated key in bits

KEY_ITERATION_COUNT

Iteration count; NIST recommends at least 1000 iterations

SALT

Salt; a random 8 bytes used to generate an encryption key from a key password / passphrase. @note The same value must be used for the salt when converting a key password/passphrase into an encryption key for both encryptionn and decryption.

Public Class Methods

base64_decode(str) click to toggle source

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

@param str [String] A base-64 encoded String. @return [Array<byte>] A Java byte-array containing the decoded bytes.

# File lib/batch-kit/encryption/java_encryption.rb, line 151
def base64_decode(str)
    javax.xml.bind.DatatypeConverter.parseBase64Binary(str)
end
base64_encode(bytes) click to toggle source

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

@param bytes [String, Array<byte>] A String or Java byte-array to be

encoded.

@return [String] A base-64 encoded String.

# 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) click to toggle source

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

@param key [SecretKeySpec] The key used for encryption. @param cipher_text [String] A base-64 encoded cipher text string that

is to be decrypted.

@param cipher_algorithm [String] The name of the cipher algorithm used

to encrypt the clear_text.

@return [String] The clear text that was encrypted.

# 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) click to toggle source

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

@param key_text [String] The clear-text pass-phrase to use as the key

for decryption.

@param cipher_text [String] A base-64 encoded cipher text string that

is to be decrypted.

@param salt [Array<Byte>] 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.

@return [String] The clear text that was encrypted.

# 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) click to toggle source

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.

@param key [SecretKeySpec] The key to use for encryption. @param clear_text [String] The cleartext string to be encrypted. @param cipher_algorithm [String] The name of the cipher algorithm to

use when encrypting the clear_text.

@return [String] A base-64 encoded string representing the encrypted

+clear_text+ value.
# 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) click to toggle source

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

@param key_text [String] The clear-text pass-phrase to use as the key

for encryption.

@param clear_text [String] The cleartext string to be encrypted. @param salt [Array<Byte>] An 8-byte array of random values to use as

the salt.

@return [String] A base-64 encoded string representing the encrypted

+clear_text+ value.
# 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) click to toggle source

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

@param key_text [String] A clear-text password or pass phrase that is

to be used to derive the encryption key.

@param salt [Array<Byte>] An 8-byte array of random values to use as

the salt.

@return [SecretKey] A key that can be used for encryption/decryption.

# 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_key() click to toggle source

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.

@return [String] A random string of text that can be used as a master

key for encrypting/decrypting other values.
# File lib/batch-kit/encryption/java_encryption.rb, line 46
def generate_master_key()
    java.util.UUID.randomUUID().toString()
end

Private Instance Methods

base64_decode(str) click to toggle source

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

@param str [String] A base-64 encoded String. @return [Array<byte>] A Java byte-array containing the decoded bytes.

# File lib/batch-kit/encryption/java_encryption.rb, line 151
def base64_decode(str)
    javax.xml.bind.DatatypeConverter.parseBase64Binary(str)
end
base64_encode(bytes) click to toggle source

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

@param bytes [String, Array<byte>] A String or Java byte-array to be

encoded.

@return [String] A base-64 encoded String.

# 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) click to toggle source

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

@param key [SecretKeySpec] The key used for encryption. @param cipher_text [String] A base-64 encoded cipher text string that

is to be decrypted.

@param cipher_algorithm [String] The name of the cipher algorithm used

to encrypt the clear_text.

@return [String] The clear text that was encrypted.

# 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) click to toggle source

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

@param key_text [String] The clear-text pass-phrase to use as the key

for decryption.

@param cipher_text [String] A base-64 encoded cipher text string that

is to be decrypted.

@param salt [Array<Byte>] 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.

@return [String] The clear text that was encrypted.

# 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) click to toggle source

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.

@param key [SecretKeySpec] The key to use for encryption. @param clear_text [String] The cleartext string to be encrypted. @param cipher_algorithm [String] The name of the cipher algorithm to

use when encrypting the clear_text.

@return [String] A base-64 encoded string representing the encrypted

+clear_text+ value.
# 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) click to toggle source

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

@param key_text [String] The clear-text pass-phrase to use as the key

for encryption.

@param clear_text [String] The cleartext string to be encrypted. @param salt [Array<Byte>] An 8-byte array of random values to use as

the salt.

@return [String] A base-64 encoded string representing the encrypted

+clear_text+ value.
# 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) click to toggle source

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

@param key_text [String] A clear-text password or pass phrase that is

to be used to derive the encryption key.

@param salt [Array<Byte>] An 8-byte array of random values to use as

the salt.

@return [SecretKey] A key that can be used for encryption/decryption.

# 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_key() click to toggle source

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.

@return [String] A random string of text that can be used as a master

key for encrypting/decrypting other values.
# File lib/batch-kit/encryption/java_encryption.rb, line 46
def generate_master_key()
    java.util.UUID.randomUUID().toString()
end