Aaron Rustad Aaron Rustad - 2 years ago 76
Ruby Question

How to encrypt a fixed size number using OpenSSL::Cipher

I need to encrypt a number using

, however I'm having difficulty understanding exactly what combination of packing I need to use to get a known result.

I have Java reference code as follows:

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import com.google.common.primitives.Longs;

class Encryptor {
private String initialVector;
private static final String TRANFORMATION = "AES/CBC/PKCS5Padding";
private static final String ALGORITHM = "AES";

String encrypt(SecretKeySpec key, long timestamp) throws Exception {
byte[] encryptedBytes = getEncryptingCipher(key).doFinal(Longs.toByteArray(timestamp));
return Base64.encodeBase64String(encryptedBytes);

private Cipher getEncryptingCipher(SecretKeySpec key) throws
NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException,
InvalidAlgorithmParameterException {
Cipher encryptingCipher = Cipher.getInstance(TRANFORMATION);
encryptingCipher.init(Cipher.ENCRYPT_MODE, key, new
return encryptingCipher;

private SecretKeySpec getSecretKeySpec(String key) throws DecoderException {
byte[] keyBytes = Hex.decodeHex(key.toCharArray());
return new SecretKeySpec(keyBytes, ALGORITHM);

void setInitialVector(String initialVector) {
this.initialVector = initialVector;

public static void main(String[] args) throws Exception {
Encryptor encryptor = new Encryptor();
//Expensive operation so only performed once, re-use the key spec instance
SecretKeySpec keySpec =
long timestamp = 1464284796L; //System.currentTimeMillis() / 1000;
String authToken = encryptor.encrypt(keySpec, timestamp);

Which results in the following
encoded string being printed on the console:

I've tried to replicate this using
, but I've had no luck. The Ruby OpenSSL documentation is lacking in detail. I suspect my use of pack is incorrect.

require "openssl"

key = ['b35901b480ca658c8be4341eefe21a80'].pack('H*')
iv = '0000000000000000'
message = [1464284796].pack "N*"

cipher = OpenSSL::Cipher::AES.new(128, :CBC)

cipher.iv = iv
cipher.key = key

encrypted = cipher.update(message)
encrypted << cipher.final

cipher64 = [encrypted].pack('m')

puts "Generated: " + cipher64
puts "Expected : " + '6BH3hg1cqQJOK6sG8gw7Xw=='

Answer Source

The Guava documentation says for Longs#toByteArray(long):

toByteArray(long value)
Returns a big-endian representation of value in an 8-element byte array; equivalent to ByteBuffer.allocate(8).putLong(value).array().

but Ruby's Array#pack "N*" encodes a 32-bit unsigned integer which results in 4 bytes. So, you could simply fill it up with 4 zeros:

message = [0, 1464284796].pack "N*"

or as matt notes in the comments using a big-endian 64-bit integer:

message = [1464284796].pack "Q>"
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download