View all files | ||||
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.
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:
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.
| 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.
| 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.