The standard encryption algorithm is AES after it got choosen and standardized by NIST (National Institute of Standards and Technology). There are 3 main parameters that need to be equal when crossing the platforms to decrypt the ciphertext.
This version is the advanced version of AES GCM mode 256 string encryption because it does not use a randomly generated AES key but a key derived from a password using the PBKDF2 key derivation. More details about this can be found in my PBKDF2 article.
This is a string (or char array in Java) and in a program it gets filled by a user input like "input password".
This is the plaintext string (on encryption side) or ciphertext string (on decryption side). As we do need the same salt, initialization vector (iv) and gcmTag on decryption side, the ciphertext is a concationation of
(Base64) salt : (Base64) nonce : (Base64) ciphertext : (Base64) gcmTag
All other parameters (number of PBKDF2 iterations, AES mode and padding) are hard-coded in the encryption and decryption functions.
The answer is easy - it is most secure AES mode available. It calculates a checksum (like a HMAC) and is often named as "tag" or "gcmTag". Some frameworks like Java append the tag to the ciphertext, others like PHP get the tag directly from the cipher engine. My programs always separate the tag from the ciphertext and transport it in an own (Base64 encoded) variable.
The program follows the usual sequence:
- input a password
- convert the plaintext to a binary format (e.g. a byte array)
- starts the encryption process
- generate a random salt for PBKDF2
- calculate the key with PBKDF2
- generate a random nonce
- set the encryption parameters
- encrypt the plaintext, prepends the salt and nonce to the ciphertext, add the gcmTag and show the result (salt:nonce:ciphertext:gcmTag) in Base64 encoding
- start the decryption process
- split the complete ciphertext-string into salt, nonce, ciphertext and gcmTag
- Base64 decoding of the salt, nonce, ciphertext and the gcmTag
- calculate the key with PBKDF2
- set the decryption parameters (same as used for encryption)
- decrypt the ciphertext and show the resulting plaintext
I don't provide a stand alone decryption only example because all parts are available in the full program.
Serious notice: although the program looks like simple there is NO CHANCE for recovering the original plaintext without the password used for encryption!
This is a serious warning regarding the security of the programs shown in these article series. Always keep in mind my disclaimer regarding my programs: All programs are for educational purposes and are not intended to use in production or any other programs where a secure solution is needed. The programs do not have proper exceptional/error handling and in some cases they use insecure key lengths or other methods that are insecure. Never ever use the programs in real life unless checked by a qualified professional cryptographer.
The following links provide the solutions in code and an online compiler that runs the code.
Language | available | Online-compiler |
---|---|---|
Java | ✅ | repl.it CpcJavaAesGcm256Pbkdf2StringEncryption |
PHP | ✅ | repl.it CpcPhpAesGcm256Pbkdf2StringEncryption |
C# | ✅ | dotnetfiddle.net CpcCsharpAesGcm256Pbkdf2StringEncryption |
Javascript CryptoJs | ❌ | not available |
NodeJS Crypto | ✅ | repl.it CpcNodeJsCryptoAesGcm256Pbkdf2StringEncryption |
NodeJS node-forge | ✅ | repl.it CpcNodeJsAesGcm256Pbkdf2StringEncryption |
Webcrypto | ✅ | your browser AesGcm256Pbkdf2StringEncryptionWebcrypto.html |
Python *1) | ✅ | repl.it CpcPythonAesGcm256Pbkdf2StringEncryption |
Go | ✅ | repl.it CpcGoAesGcm256Pbkdf2StringEncryption |
Dart *2) | ✅ | no online compiler available |
*1) you need the external library pycryptodome, version 3.9.9
*2) Dart needs the external library pointycastle version 3.1.1
An important note about the Webcrypto-program: the program is of very poor quality and should be used for demonstration purpose only. It has a lot of unnecessary conversions - never ever use it as basis for your own (business) programs.
This is an output (as there are random elements your output will differ):
AES GCM 256 String encryption with PBKDF2 derived key
plaintext: The quick brown fox jumps over the lazy dog
* * * Encryption * * *
ciphertext (Base64): rGiDbmbO3BbHJFzEdxC82oNhdzyfp//ZT/F1YEdToGw=:sokNSXKF02BDnWiE:+4R9e3BE52LhiNZ4GvzcDybPmfLLY2/Bg0tT0F2JpX9tOfajy0thEkrYmw==:mmmdJ2Xkj6T6GL56x0Io2w==
output is (Base64) salt : (Base64) nonce : (Base64) ciphertext : (Base64) gcmTag
* * * Decryption * * *
ciphertext (Base64): rGiDbmbO3BbHJFzEdxC82oNhdzyfp//ZT/F1YEdToGw=:sokNSXKF02BDnWiE:+4R9e3BE52LhiNZ4GvzcDybPmfLLY2/Bg0tT0F2JpX9tOfajy0thEkrYmw==:mmmdJ2Xkj6T6GL56x0Io2w==
input is (Base64) salt : (Base64) nonce : (Base64) ciphertext : (Base64) gcmTag
plaintext: The quick brown fox jumps over the lazy dog
This is the output of the (browser based) WebCrypto:
AES GCM 256 String encryption with PBKDF2 derived key
Important note: this program is doing what it promises but the programming itself is of very poor quality and for demonstration purposes only. Never ever use this program as source for your own programs because there are a lot of conversions to get it run.
Plaintext: The quick brown fox jumps over the lazy dog
Secret password: secret password
CiphertextCpc: 0hjPdiaEjzCYpYbfXWb47U9Yz2vcqTbo+2ixn6dYZxQ=:hx2yzgjkpB0oB+qj4HK1pg==:obDSutcfyv4mNn6SIpR/5cP+rccR0lEwi27lXxWDadOmfC51zi2fECXN3mjCb7pF
Ciphertext is (Base64) salt : (Base64) nonce : (Base64) ciphertext : (Base64) gcmTag
DecryptedtextCpc: The quick brown fox jumps over the lazy dog
Last update: Aug. 18th 2021
Back to the main page: readme.md