Hey!

Thanks for the interest in Lockbox. Please note that this project is still in the early phases of development. Whilst the concept of simple encryption for use in applications will not change, the implementation is almost certain to at this point.

In particular, the switch will probably be made in the near future from public key encryption to symmetric encryption. If you're looking for a good public-key based solution, perhaps take a look at PGP.

Lockbox by Eloquent

Lockbox is the simplest possible way to implement strong two-way encryption for use in applications. Lockbox uses a combination of well-established technologies to ensure the safety of data.

Lockbox = Simple, strong encryption.

Lockbox libraries

Why use Lockbox?

Avoiding poor choices

Encryption is a complicated subject. The are a myriad of options to choose from when deciding on an encryption scheme: algorithms, key sizes, modes, padding schemes, and encodings. Knowing what choices to make can be daunting even with a decent knowledge of cryptography.

Lockbox removes the burden of overwhelming choice. There is no configuration; Lockbox simply works in the best possible way straight out of the box.

Cross-platform compatibility

Anyone who's ever attempted to encrypt data in one language, and decrypt it in another, can explain how much of an arduous task it can be. Encryption must work exactly, byte-for-byte, the same across platforms in order to be compatible.

Libraries for Lockbox are available in multiple languages. Any combination of these libraries will work together flawlessly without any extra effort on the developer's part.

Excellent portability

Storage and/or transmission of encrypted data can pose problems of its own. Usually, the ciphertext produced by an encryption algorithm contains data that cannot be represented as a 'normal' string of text. This raw data is easily misinterpreted, and hence corrupted, by databases and other systems that may have to handle the data. The most common solution to this issue is to encode the data using something like Base64 encoding; but even Base64 causes issues for URIs and file names.

Lockbox uses a variant of Base64 designed specifically to address these issues. It's almost impossible to accidentally corrupt the data produced by Lockbox.

Public-key flexibility

Public-key cryptography allows for more flexible usage than symmetric cryptography. Encryption requires only the public key, but decryption requires access to the private key. This means that the public key can be published without compromising security. The practical upshot is that data can be securely shared without an initial secured exchange of secret keys.

Lockbox implements a public-key encryption system, allowing the developer to harness these features if they are required.

Standard key format support

Different platforms have differing levels of support for certain key formats. For example, Java has no built-in support for the default PEM format keys produced by OpenSSL. Lockbox fills in the gaps in support, and uses the same key format across all platforms, which allows for extremely simple key management.

Design goals for Lockbox

How does Lockbox actually work?

Lockbox with keys

Lockbox uses OpenSSL with PEM formatted keys, and is similar in operation to the PHP functions openssl_seal() and openssl_open().

Where Lockbox differs, is in its use of AES-256 instead of RC4 as the secondary encryption algorithm. In addition, Lockbox includes data verification steps that allow unsuccessful decryption to be detected.

Encryption process

  1. Some data and an RSA public key are passed to Lockbox.
  2. A random 256-bit key and 128-bit initialization vector (IV) are generated from a cryptographically secure source.
  3. The generated key and IV are concatenated together and encrypted with the public key using RSA encryption and OAEP padding (with SHA-1 as the hash function and MGF1 as the mask generation function) in electronic codebook mode.
  4. A SHA-1 hash of the supplied data is concatenated to the end of the data.
  5. The data and hash are encrypted using the generated key and IV and AES encryption and PKCS #7 padding (also known as PKCS #5 padding) in cipher block chaining mode.
  6. The encrypted key and IV, and the encrypted data and hash are concatenated together.
  7. This concatenation of encrypted data is then encoded using Base64 with a URI and filename safe alphabet.
  8. This encoded data is returned as the final ciphertext.

Decryption process

  1. Some ciphertext and an RSA private key are passed to Lockbox.
  2. The ciphertext is decoded using Base64 with a URI and filename safe alphabet.
  3. The first n bits of the ciphertext are extracted, where n is the size of the private key; this extracted data is the encrypted key and initialization vector.
  4. The remaining bits of the ciphertext are extracted as the encrypted data.
  5. The encrypted key and IV from step 3 are decrypted with the private key using RSA encryption and OAEP padding (with SHA-1 as the hash function and MGF1 as the mask generation function) in electronic codebook mode.
  6. The first 256 bits of the decrypted data are extracted as the key.
  7. The next 128 bits of the decrypted data are extracted as the IV.
  8. The encrypted data from step 4 is decrypted using the recovered key and IV from steps 6 and 7, and AES encryption with PKCS #7 padding (also known as PKCS #5 padding) in cipher block chaining mode.
  9. The last 160 bits of the unpadded data are the verification hash.
  10. The unpadded data before this point is considered the final data.
  11. If the verification hash matches the SHA-1 hash of the final data, the final data is returned, otherwise decryption has failed.

Reference keys

All test vectors use the following keys:

2048-bit key

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAy8jsljdxzsgvboCytmlH3Q03v30fPTNfMqmz2Yn0GdtkqQH0
1+H9y5bWWCQyeGOATvIPrELGeB9nRlQeaTb5VjCl1V9PYeM6Q30PK6411fJexjYA
/UbRG/9I/K+A9UBfJvUsjGVUMxZR8n8jmmSy8G2eqXBbP6dEZFnO0V274TRTB3SL
KD2tfYBYwMtXqT+rSbH1OyoS29A03FaUgkRk1er2i3ldyNIG8vMGv7Iagup69yBr
t8xo61IFj76dkocbozp1Y4SGzyjkR/ukRSLe+0ejS4eMyziaH7J52XX1rDFreinZ
ZDoE571ameu0biuM6aT8P1pk85VIqHLlqRm/vQIDAQABAoIBAAlqWyQFo8h+D1L3
t0oeSye3eJ/sVAkr2nYoyRp/+TtIm7oDUSC4XFWPvo+L/Jj7X+5F2NuIqkraiJcD
Q/RwicylqsPVB4HqUcLUgGLwRaSA8kgOLrWFFBxLC0BBi5/JPZw7L7e85ssFePvP
TAHSLUJWjkId4tlqDQrl61xZDFk3UHawcovZeUp4RAqULeLDXAQTQJYXE8erPjhQ
Y0uSWORe1S1ICaI2aqbjmIHFUzPlz45KlakzLwn4tobeiKeNaHrPw++JMXNVSlPk
hGxPliXbZauaoDHa/p6w3hDvr2ZjOLU7QDHgdiWZ4EUW5AQRf7aiKtE2yNPTGJQb
yv9QHzECgYEA/UQluesABp+UJvvDzbEmDkipgCbEu5fHyGb8C0FPZET1ys2wu0DI
IaYR4hiYetrv5inHzXnMSkuQSMzPa+SyBXgiGnB9J2+sBX0H9byq3QuMriTSDQPA
ptxZlYAXTEXRUsNYG3/VCiC75VjbufHI7QmsOStTij6w15gchTrBt+cCgYEAzfwL
amiGmgVblJ1xr+8zwZMv99c22j8K+Cm4PoUhQ6I6XcgqHyDj8mD65UxQU3aE8R2m
vbX7XW1jrpflbVwoRoJS9z8F77rm6t38yS3WJqz6kyoQ0u4W2m8D8g/WWROjeGFD
ljrpiwErkmzCGrNhSk4O9YTXrNUGkD5MTpVPBrsCgYBlmdgUnIy3G3+AoBFty/o7
UrUE3wifRQV1hLLqBPpHfE6qXBfhFtzyer/D1yAccQY6bFpmOM1WpLeuLNOtMeKk
xQvRVX0vu+HjlcQCtfxJjt+R4N2PMQkxJ0ac7fTquTt/GzSWW5LobDdUi3AiSTfU
t8Oqb5Ik7H9fDfurCuY50wKBgQDDC/wfSVTTeWlLo35oct+WV/JfA7ocFQAlFxQw
l011RqNv9D72dOWDuJM7FvUk4yBlVId0MmMQB6oRRCHqWQ6GHZfEKThM1bUdBxD7
ytxyiO9I9NczdGHNervItXhppq/vKGKgWa6VgokowLVYJS1l994wXBcBwEHTyjnl
W3qWSwKBgQDZo0uMMWevRBriPT6OCdEYwnOZOMvh6LdXG2wyC2wYMY+8XOMzDrZP
zD3i4wQYCfJg7pyhVtctBz2NQ8J878xm2EXzUpGaIxjLIXb1UVgw4XXcM7LkjFaa
J1iMrMTLGSX89+gW3Bg8hxS7klxZf7ZlVSzLpA2jkK3k5vdgWGVhtA==
-----END RSA PRIVATE KEY-----

4096-bit key

-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

Test vectors

All test vector values below are expressed as US-ASCII encoded strings, except the key names which are references to the relevant test key. Newlines are added only for readability, and do not make up part of the value.

Note that the RSA encrypted portion of the ciphertext will be different each time because it utilizes a random seed. Therefore, for the 2048-bit key, only the ciphertext after the 342nd byte is guaranteed to be the same for all ciphertext. For the 4096-bit key, only the ciphertext after the 684th byte is guaranteed to be the same for all ciphertext.

Key:                <2048-bit key>
Data:               <empty>
Generated key:      12345678901234567890123456789012
Generated IV:       1234567890123456
Example ciphertext: QJyn73i2dlN_V9o2fVLLmh4U85AIEL5v
                    Cch2sP5aw3CogMBn5qRpokg6OFjRxsYB
                    xb_Oqe8n9GALxJsuuqyZgWXxSK0exA2P
                    QnAECIcujG9EyM4GlQodJiJdMtDJh0Dd
                    frp7s87w7YWgleaK_3JVqEpjRolj1AWr
                    DjXeFDl_tGIZ1R95PD2mbq6OUgm1Q56M
                    CRLZdZJOm3yixcGHQOV2wv73YIbOvOa8
                    hEZ7ydX-VRHPMmJyFgUe9gv8G8sDm6xY
                    UEz1rIu62XwMoMB4B3UZo_r0Q9xCr4sx
                    BVPY7bOAp6AUjOuvsHwBGJQHZi3k665w
                    mShg7pw8HFkr_Fea4nzimditNTFRhW3K
                    MfhqusPDqWJ7K37AvEHDaLULPKBNj24c

Key:                <2048-bit key>
Data:               1234
Generated key:      12345678901234567890123456789012
Generated IV:       1234567890123456
Example ciphertext: MFq4hhLJN8_F6ODUWX20tO4RIJURlMHA
                    mdujFMTyqc2Y3zHIXzmaK4CcoThggqZX
                    44-4kbhjwk9ihwuzS4GAQuSCCdoh5xzT
                    WfeboPu6zE51BrZQdz67VavvmvpHVdGg
                    oQcSsa_GiZcc7aBYh-AhfCyHrPb-r1hN
                    y_AWXv8hcO8mIS1fJ3Mvtr3Xxfwlydrn
                    23YUwuOG-tX4FctKqh2eFFkrht53ZwVv
                    7q67U3x774KjbUpB4LbML6APxe4ucghl
                    DpY_A_DFLH2GlvvouVaT3jCibkY_yIMC
                    1lNSBIdgpKGoAoZWy4bIpqDUu0SiLvDO
                    mclpPRARakRr15F21a_MQ9wL_JNwnG1u
                    T1zKZNgUcr2GaWk31ahOBKB0lfr-E7W2

Key:                <2048-bit key>
Data:               1234567890123456
Generated key:      12345678901234567890123456789012
Generated IV:       1234567890123456
Example ciphertext: oFqfBVNvWyUYThQiA54V_Lpx6Ka2zqEF
                    QCQBxcYhnbG2uuShACbf3I31USwRCFDV
                    mBLmfcO4ReMJFQzen-tRRuapOQ4Pjzdp
                    IRw_T9wYjj0n3Sjs1NZnDbN3hbHCmXoq
                    sl0byi0Lr5hwhmqOCj7Po5ey4EsPpuqb
                    tPx38PPae-zOlnMrdYuKhV8jIMDSsslf
                    VWMOgUlYnDOt9Pd1NEJkJE-GxYIYyzPB
                    _NtxwQf5moDjsNzxtx5fzEejo8BGDQ5Q
                    phjkQCBmMWd1fKN3Z3aBSNn_WS2HwxzU
                    gl10lzaHityP9iZU2DY8qkQB_wSk7-pf
                    h05CITq0DPIOHDQzVkcWlnuUZ55SZL-E
                    BpxoZDMH74B7GmHK66rSGH0MoSGY1fZC
                    hAWyjRKa0nWslBVkLoJRUg

Key:                <4096-bit key>
Data:               1234567890123456
Generated key:      12345678901234567890123456789012
Generated IV:       1234567890123456
Example ciphertext: rqA8g_yyA0eeLoun6rqnUxgy3JnIS9p8
                    bAgZYf4774ZahHcFCOozwWbMU_0HVMS9
                    sOlAmr-dQl6RqDaOLfAxrHq3mluFSlXf
                    gcJXrvPtf27u_4NCHXuwm825ptpmprPx
                    wl0z4tz6u-fqNBSfQuHApZ3MvAGsEa0v
                    b0IftBX0q8tKL6sdCx6WpTGcynEdxLcZ
                    Tx6cM4LRdcjL3SQZ5vk4VF69lS2r1WgJ
                    h8eUa_VwgsqhTkoc7wJAECqxHBQSh6q-
                    GOt6bpVnlaGkM_BfcrB5SJdtcEZd5BgG
                    xG8QwQGwsT60jErxpd5rYLfBrG7kgVse
                    yksfN-99-kUHQpkwCIS_zS5bpr3hLpBi
                    UhSA4638Xgd2qyAZCgl3OBY56HSdncZq
                    5o4xGycM69eN5hb-c852W-dP6S49BXSn
                    3OpmEOkZoIeNw0EYHpLLpfaLwafIVdLC
                    bQZX1g_szDcBDyyM-PN5-jnuaqySRywF
                    rMj56U9vAvwtFMaHKY-ll4Qxf8PgoDWM
                    7KogGgkztlZ0ZzaMwBLQeTDpjbNl5NXJ
                    CxobJfGv8w6zQZmDz8J2K3DsQrDmZid_
                    W6Gtsv7XsSnY-gl6TD4IkK1VEKnttqXa
                    PfVdCNadtQ-Z1INiK2pa3F0NKs4POO-K
                    PpW68kQ5l2qeUAVv6B-QdcwunyMh9XO_
                    vGx8Wf8SrbZ7lGeeUmS_hAacaGQzB--A
                    exphyuuq0hh9DKEhmNX2QoQFso0SmtJ1
                    rJQVZC6CUVI