This repository was created to address the ever-growing number of poor encryption code examples that float about the internet. This repository will expand over time to include examples in more languages.
As of April 2021, there are 18 different compatible examples for 15 different languages across 5 different platforms.
- Encryption: AES-128-GCM
- Key Deriviation: PBKDF2
- PBKDF2 Underlying Hash: SHA-256
AES with a 128-bit key was chosen due to the Java Unlimited Strength Policy
that requires key sizes of no more than 128-bits due to cryptography export laws. While the
examples are shown using AES-128, they can be trivially changed to 256-bit AES
by changing the ALGORITHM_KEY_SIZE
(and in some cases, ALGORITHM_NAME
) parameter.
Every example shown here is compatible across platforms and/or languages. The result of encryptString
in any language can be decrypted by decryptString
in any language. Please do not submit pull requests for examples that are not compatible with the existing examples.
Each example exposes 4 methods with signatures that are roughly equivalent to the following:
string encryptString(plaintext: string, password: string)
string decryptString(ciphertext: string, password: string)
byte[] encrypt(plaintext: byte[], key: byte[])
byte[] decrypt(ciphertext: byte[], key: byte[])
As is expected, the encrypt
and decrypt
methods operate on and return raw
binary data. The *string
methods, however, take string parameters and return base64 encoded strings. The password
parameter is fed through PBKDF2 first. password
can be of any length but key
must be 128-bits in length. You can change the AES key size by adjusting the ALGORITHM_KEY_SIZE
parameter, and in some examples, the ALGORITHM_NAME
parameter too.
NOTE: Because of the use of PBKDF2, the binary vs string methods are not compatible.
Language | Version Tested | Dependencies | Notes |
---|---|---|---|
Java | Java 8 JRE | ||
Kotlin | Java 8 JRE | ||
JavaScript (Node) | NodeJS 8.4.0 | Tested on 8.4.0, but supported in versions as early as 4.0.0 | |
JavaScript (Browser) | Requires base64-js | Uses the WebCrypto API, ensure browser support before using this example. | |
JavaScript (SJCL) | Requires the Stanford JavaScript Crypto Library | Doesn't run asynchronously. | |
Go | Go 1.9 | golang.org/x/crypto/pbkdf2 |
Tested on 1.9 but supported in earlier versions. |
Python | v3.6.4 | Requires PyCryptodome | No support for Python 2. |
Ruby | v2.4.4 | Uses the OpenSSL Gem | |
Visual Basic .NET | .NET 4.5 | Requires BouncyCastle. | |
C# | .NET 4.5 | Requires BouncyCastle. | |
C | Requires OpenSSL libssl-dev | Uses SCEE.h header file. |
|
C++ | Requires C++11 Compiler | Requires OpenSSL libssl-dev | Wrapper for the C example. Requires SCEE.h and SCEE_cpp.h |
Objective-C | Requires OpenSSL libssl-dev | Wrapper for the C example. Requires SCEE.h and SCEE_objc.h |
|
Rust | v1.30.0 | Requires the ring v0.13.2 and base64 v0.9.3 crates | |
Swift | Swift 4.0 | Requires SwiftGCM. | Must use a bridge for CommonCrypto. |
PHP | Requires PHP 7 | Uses random_bytes which requires PHP 7. |
|
Perl | Perl 5 | Requires CryptX |
The following ciphertexts are the results of encryptString
using the given password. If your implementation can encryptString
and decryptString
using the code you've written, and can also decryptString
the ciphertexts below to the same given result, then it is suitable for inclusion in this repository. Recall that, due to a randomly generated salt and nonce, the following are not expected outputs for encryptString
, they are for testing decryptString
only.
Ciphertext | Password | Plaintext |
---|---|---|
CqjxsXq6Y5ebtW6w98UQfgwdOpaCCkCy0l1qK5gJfhZnKVhp4+OuvxoiigHi8mO1R8CAyl5t |
DTY62mV2Cv | XCbJbjd72q |
VtHh3Z6jqJpIDK0yLe4+/UNpxqBqcmaiJWmaecb7qfCyOlAcVJ973zBNM51VCup5UTuVlu3H |
Pl4WODjq4k | SOJHSCm4qR |
SNQHdWnlcmJELLKewNTxBhzmJ1U+ChqKK5Kdvd/FSKssHW5b8y8SOrNVHdm78JUAYpGKlEUD |
BZO8PUEysY | NYzd53moLT |
5EmCwwSWj6YYgxBlld6DFW8I+QXCWxz5g/laEwUYV/DuoCGvxbW4ZlMd1Tsj4N07WbBOhIJU |
OziaxPFGYh | vW1Qjb30mt |
7miUNuhjJPAlbIHYKA2v/iBH3aplFF0pGw6HQAD5tKluh/1M69MLQ9xIkVcGfTr0CycsTFLU |
gkLDY5mmzT | 9z19eFctoZ |
0iqwbC8/1YvTsl2dog6aXaGfXVypsv1BcbnDE06C7nl9REITn3NW18+ZUmc= |
Empty String | Empty String |
The C example requires a bit more effort to understand and use properly due to varying buffer sizes with regard to base64 padding. The example below shows how to use crypt_string_get_length
to determine what buffer size you will need to allocate to store the result.
#include "SCEE.h"
#include <stdio.h>
int main(int argc, char* argv[]) {
// Our plaintext and password.
unsigned char plaintext[] = "Hello, World!";
unsigned char password[] = "OddShapelyOak7332";
// Make enough space for our ciphertext.
// Note that scee_crypt_string_get_length will give us the size of the buffer we
// need INCLUDING the null character.
size_t ct_length = scee_crypt_string_get_length(strlen(plaintext), SCEE_CRYPT_ENCRYPT);
unsigned char ciphertext[ct_length];
// Encryption.
// The operation places the null character at the end of the buffer for us.
int r = scee_encrypt_string(plaintext, strlen(plaintext), password, strlen(password), ciphertext);
if (r != SCEE_OK) { return 1; }
// Output for Encryption.
printf("Ciphertext Buffer Size: %zu\n", ct_length);
printf("Ciphertext strlen : %zu\n", strlen(ciphertext));
printf("Ciphertext : %s\n\n", ciphertext);
// Make enough space for our plaintext again.
// Note that because of base64 padding, scee_crypt_string_get_length will
// usually tell us that we need more space than we do. We can get the
// actual length of the plaintext after we decrypt.
size_t pt_max_length = scee_crypt_string_get_length(strlen(ciphertext), SCEE_CRYPT_DECRYPT);
size_t pt_actual_length;
unsigned char plaintext2[pt_max_length];
// Decryption.
// The operation places the null character at the end of the buffer for us.
r = scee_decrypt_string(ciphertext, strlen(ciphertext), password, strlen(password), plaintext2, &pt_actual_length);
if (r != SCEE_OK) { return 1; }
// Output for Decryption.
printf("Plaintext Buffer Size: %zu\n", pt_max_length);
printf("Plaintext Actual Size: %zu\n", pt_actual_length);
printf("Plaintext strlen : %zu\n", strlen(plaintext));
printf("Plaintext : %s\n\n", plaintext);
return 0;
}