-
-
Save thackerronak/554c985c3001b16810af5fc0eb5c358f to your computer and use it in GitHub Desktop.
AES encryption/decryption in crypto-js way, use KDF for generating IV and Key, use CBC with PKCS7Padding for Cipher
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AES encryption/decryption use in Android JAVA and JavaScript (JS). | |
Add dependencies in gradle file | |
android { | |
packagingOptions { | |
exclude 'META-INF/jersey-module-version' | |
} | |
} | |
dependencies { | |
compile group: 'com.sun.jersey', name: 'jersey-client', version: '1.19.4' | |
compile group: 'org.bouncycastle', name: 'bcprov-jdk16', version: '1.46' | |
} | |
Code for JAVA and Import AESHelper class | |
try { | |
String text="1df43d5d67dc1aea6d0a0b44dcf2495c8ac290846a6ffae818a755de4e8d59"; | |
String chipherText=AESHelper.encrypt("Abcd@123",text); | |
Log.d("---",chipherText); | |
String dycrpt = AESHelper.decrypt("Abcd@123",chipherText); | |
Log.d("---",dycrpt); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
Code for JS | |
var CryptoJS = require('crypto-js'); | |
var encrypted = CryptoJS.AES.encrypt("1df43d5d67dc1aea6d0a0b44dcf2495c8ac290846a6ffae818a755de4e8d59", "Abcd@123"); | |
console.log(encrypted.toString()); | |
var decrypted = CryptoJS.AES.decrypt(encrypted.toString(), "Abcd@123"); | |
var plaintext = decrypted.toString(CryptoJS.enc.Utf8); | |
console.log(plaintext.toString()); | |
Check Online | |
https://www.browserling.com/tools/aes-encrypt | |
https://www.browserling.com/tools/aes-decrypt |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.sun.jersey.core.util.Base64; | |
import java.io.UnsupportedEncodingException; | |
import java.security.InvalidAlgorithmParameterException; | |
import java.security.InvalidKeyException; | |
import java.security.MessageDigest; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.SecureRandom; | |
import java.util.Arrays; | |
import java.util.Random; | |
import javax.crypto.BadPaddingException; | |
import javax.crypto.Cipher; | |
import javax.crypto.IllegalBlockSizeException; | |
import javax.crypto.NoSuchPaddingException; | |
import javax.crypto.SecretKey; | |
import javax.crypto.spec.IvParameterSpec; | |
import javax.crypto.spec.SecretKeySpec; | |
public class AESHelper { | |
/** | |
* | |
* Conforming with CryptoJS AES method | |
* **** YOU NEED TO ADD "JCE policy" to have ability to DEC/ENC 256 key-lenght with AES Cipher **** | |
* | |
*/ | |
// Prevent facing error when using "PKCS7Padding" in Cipher | |
// add Bouncycastle provider [link=http://www.bouncycastle.org/latest_releases.html] | |
static { | |
java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); | |
} | |
static int KEY_SIZE = 256; | |
static int IV_SIZE = 128; | |
static String HASH_CIPHER = "AES/CBC/PKCS7Padding"; | |
static String AES = "AES"; | |
static String CHARSET_TYPE = "UTF-8"; | |
static String KDF_DIGEST = "MD5"; | |
// Seriously crypto-js, what's wrong with you? | |
static String APPEND = "Salted__"; | |
/** | |
* Encrypt | |
* @param password passphrase | |
* @param plainText plain string | |
*/ | |
public static String encrypt(String password,String plainText) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { | |
byte[] saltBytes = generateSalt(8); | |
byte[] key = new byte[KEY_SIZE/8]; | |
byte[] iv = new byte[IV_SIZE/8]; | |
EvpKDF(password.getBytes(CHARSET_TYPE), KEY_SIZE, IV_SIZE, saltBytes, key, iv); | |
SecretKey keyS = new SecretKeySpec(key, AES); | |
Cipher cipher = Cipher.getInstance(HASH_CIPHER); | |
IvParameterSpec ivSpec = new IvParameterSpec(iv); | |
cipher.init(Cipher.ENCRYPT_MODE, keyS, ivSpec); | |
byte[] cipherText = cipher.doFinal(plainText.getBytes(CHARSET_TYPE)); | |
// Thanks kientux for this: https://gist.github.com/kientux/bb48259c6f2133e628ad | |
// Create CryptoJS-like encrypted ! | |
byte[] sBytes = APPEND.getBytes(CHARSET_TYPE); | |
byte[] b = new byte[sBytes.length + saltBytes.length + cipherText.length]; | |
System.arraycopy(sBytes, 0, b, 0, sBytes.length); | |
System.arraycopy(saltBytes, 0, b, sBytes.length, saltBytes.length); | |
System.arraycopy(cipherText, 0, b, sBytes.length + saltBytes.length, cipherText.length); | |
byte[] bEncode = Base64.encode(b); | |
return new String(bEncode); | |
} | |
/** | |
* Decrypt | |
* Thanks Artjom B. for this: http://stackoverflow.com/a/29152379/4405051 | |
* @param password passphrase | |
* @param cipherText encrypted string | |
*/ | |
public static String decrypt(String password,String cipherText) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { | |
byte[] ctBytes = Base64.decode(cipherText.getBytes(CHARSET_TYPE)); | |
byte[] saltBytes = Arrays.copyOfRange(ctBytes, 8, 16); | |
byte[] ciphertextBytes = Arrays.copyOfRange(ctBytes, 16, ctBytes.length); | |
byte[] key = new byte[KEY_SIZE/8]; | |
byte[] iv = new byte[IV_SIZE/8]; | |
EvpKDF(password.getBytes(CHARSET_TYPE), KEY_SIZE, IV_SIZE, saltBytes, key, iv); | |
Cipher cipher = Cipher.getInstance(HASH_CIPHER); | |
SecretKey keyS = new SecretKeySpec(key, AES); | |
cipher.init(Cipher.DECRYPT_MODE, keyS, new IvParameterSpec(iv)); | |
byte[] plainText = cipher.doFinal(ciphertextBytes); | |
return new String(plainText); | |
} | |
private static byte[] EvpKDF(byte[] password, int keySize, int ivSize, byte[] salt, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException { | |
return EvpKDF(password, keySize, ivSize, salt, 1, KDF_DIGEST, resultKey, resultIv); | |
} | |
private static byte[] EvpKDF(byte[] password, int keySize, int ivSize, byte[] salt, int iterations, String hashAlgorithm, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException { | |
keySize = keySize / 32; | |
ivSize = ivSize / 32; | |
int targetKeySize = keySize + ivSize; | |
byte[] derivedBytes = new byte[targetKeySize * 4]; | |
int numberOfDerivedWords = 0; | |
byte[] block = null; | |
MessageDigest hasher = MessageDigest.getInstance(hashAlgorithm); | |
while (numberOfDerivedWords < targetKeySize) { | |
if (block != null) { | |
hasher.update(block); | |
} | |
hasher.update(password); | |
block = hasher.digest(salt); | |
hasher.reset(); | |
// Iterations | |
for (int i = 1; i < iterations; i++) { | |
block = hasher.digest(block); | |
hasher.reset(); | |
} | |
System.arraycopy(block, 0, derivedBytes, numberOfDerivedWords * 4, | |
Math.min(block.length, (targetKeySize - numberOfDerivedWords) * 4)); | |
numberOfDerivedWords += block.length/4; | |
} | |
System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4); | |
System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4); | |
return derivedBytes; // key + iv | |
} | |
private static byte[] generateSalt(int length) { | |
Random r = new SecureRandom(); | |
byte[] salt = new byte[length]; | |
r.nextBytes(salt); | |
return salt; | |
} | |
} |
Thanks for documenting the exact behavior of CryptoJS.AES.encrypt()
; this was super useful to build an equivalent Python encrypt/decrypt! ππ»
Thanks for documenting the exact behavior of
CryptoJS.AES.encrypt()
; this was super useful to build an equivalent Python encrypt/decrypt! ππ»
Can you please share python code ?
Thanks for documenting the exact behavior of
CryptoJS.AES.encrypt()
; this was super useful to build an equivalent Python encrypt/decrypt! ππ»Can you please share python code ?
https://github.com/keyiflerolsun/Kekik/blob/main/Kekik/Sifreleme/CryptoJS.py
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
aren't bouncy castle algorithms deprecated on Android?