Last active
April 30, 2021 09:07
-
-
Save m1entus/f70d4d1465b90d9ee024 to your computer and use it in GitHub Desktop.
This file contains 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
// http://stackoverflow.com/questions/17535918/aes-gets-different-results-in-ios-and-java | |
/** | |
* Encodes a String in AES-256 with a given key | |
* | |
* @param context | |
* @param password | |
* @param text | |
* @return String Base64 and AES encoded String | |
*/ | |
public static String encode(String keyString, String stringToEncode) throws NullPointerException { | |
if (keyString.length() == 0 || keyString == null) { | |
throw new NullPointerException("Please give Password"); | |
} | |
if (stringToEncode.length() == 0 || stringToEncode == null) { | |
throw new NullPointerException("Please give text"); | |
} | |
try { | |
SecretKeySpec skeySpec = getKey(keyString); | |
byte[] clearText = stringToEncode.getBytes("UTF8"); | |
// IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID | |
final byte[] iv = new byte[16]; | |
Arrays.fill(iv, (byte) 0x00); | |
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); | |
// Cipher is not thread safe | |
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); | |
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec); | |
String encrypedValue = Base64.encodeToString(cipher.doFinal(clearText), Base64.DEFAULT); | |
Log.d("jacek", "Encrypted: " + stringToEncode + " -> " + encrypedValue); | |
return encrypedValue; | |
} catch (InvalidKeyException e) { | |
e.printStackTrace(); | |
} catch (UnsupportedEncodingException e) { | |
e.printStackTrace(); | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} catch (BadPaddingException e) { | |
e.printStackTrace(); | |
} catch (NoSuchPaddingException e) { | |
e.printStackTrace(); | |
} catch (IllegalBlockSizeException e) { | |
e.printStackTrace(); | |
} catch (InvalidAlgorithmParameterException e) { | |
e.printStackTrace(); | |
} | |
return ""; | |
} | |
/** | |
* Decodes a String using AES-256 and Base64 | |
* | |
* @param context | |
* @param password | |
* @param text | |
* @return desoded String | |
*/ | |
public String decode(String password, String text) throws NullPointerException { | |
if (password.length() == 0 || password == null) { | |
throw new NullPointerException("Please give Password"); | |
} | |
if (text.length() == 0 || text == null) { | |
throw new NullPointerException("Please give text"); | |
} | |
try { | |
SecretKey key = getKey(password); | |
// IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID | |
final byte[] iv = new byte[16]; | |
Arrays.fill(iv, (byte) 0x00); | |
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); | |
byte[] encrypedPwdBytes = Base64.decode(text, Base64.DEFAULT); | |
// cipher is not thread safe | |
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); | |
cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec); | |
byte[] decrypedValueBytes = (cipher.doFinal(encrypedPwdBytes)); | |
String decrypedValue = new String(decrypedValueBytes); | |
Log.d(LOG_TAG, "Decrypted: " + text + " -> " + decrypedValue); | |
return decrypedValue; | |
} catch (InvalidKeyException e) { | |
e.printStackTrace(); | |
} catch (UnsupportedEncodingException e) { | |
e.printStackTrace(); | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} catch (BadPaddingException e) { | |
e.printStackTrace(); | |
} catch (NoSuchPaddingException e) { | |
e.printStackTrace(); | |
} catch (IllegalBlockSizeException e) { | |
e.printStackTrace(); | |
} catch (InvalidAlgorithmParameterException e) { | |
e.printStackTrace(); | |
} | |
return ""; | |
} | |
/** | |
* Generates a SecretKeySpec for given password | |
* | |
* @param password | |
* @return SecretKeySpec | |
* @throws UnsupportedEncodingException | |
*/ | |
private static SecretKeySpec getKey(String password) throws UnsupportedEncodingException { | |
// You can change it to 128 if you wish | |
int keyLength = 256; | |
byte[] keyBytes = new byte[keyLength / 8]; | |
// explicitly fill with zeros | |
Arrays.fill(keyBytes, (byte) 0x0); | |
// if password is shorter then key length, it will be zero-padded | |
// to key length | |
byte[] passwordBytes = password.getBytes("UTF-8"); | |
int length = passwordBytes.length < keyBytes.length ? passwordBytes.length : keyBytes.length; | |
System.arraycopy(passwordBytes, 0, keyBytes, 0, length); | |
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); | |
return key; | |
} |
This file contains 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
NSString *text = @"text"; | |
NSString *key32 = @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; | |
NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding]; | |
NSString *encryptedData = [[data AES256EncryptWithKey:key32] base64EncodedStringWithOptions:0]; | |
NSLog(@"%@",encryptedData); # => QfpLKBn20BZI1NIhigOo6g== |
This file contains 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
crypto = require('crypto') | |
key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' | |
iv = new Buffer(16) | |
iv.fill(0) | |
text = 'text' | |
cipher = crypto.createCipheriv('aes-256-cbc', key, iv) | |
output = cipher.update('text', 'utf8', 'base64') | |
output += cipher.final('base64') | |
console.log output # => QfpLKBn20BZI1NIhigOo6g== |
This file contains 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
// http://stackoverflow.com/questions/17535918/aes-gets-different-results-in-ios-and-java | |
- (NSData *)AES256EncryptWithKey:(NSString *)key { | |
// 'key' should be 32 bytes for AES256, will be null-padded otherwise | |
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused) | |
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) | |
// fetch key data | |
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; | |
NSUInteger dataLength = [self length]; | |
//See the doc: For block ciphers, the output size will always be less than or | |
//equal to the input size plus the size of one block. | |
//That's why we need to add the size of one block here | |
size_t bufferSize = dataLength + kCCBlockSizeAES128; | |
void *buffer = malloc(bufferSize); | |
size_t numBytesEncrypted = 0; | |
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, | |
keyPtr, kCCKeySizeAES256, | |
NULL /* initialization vector (optional) */, | |
[self bytes], dataLength, /* input */ | |
buffer, bufferSize, /* output */ | |
&numBytesEncrypted); | |
if (cryptStatus == kCCSuccess) { | |
//the returned NSData takes ownership of the buffer and will free it on deallocation | |
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; | |
} | |
free(buffer); //free the buffer; | |
return nil; | |
} | |
- (NSData *)AES256DecryptWithKey:(NSString *)key { | |
// 'key' should be 32 bytes for AES256, will be null-padded otherwise | |
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused) | |
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) | |
// fetch key data | |
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; | |
NSUInteger dataLength = [self length]; | |
//See the doc: For block ciphers, the output size will always be less than or | |
//equal to the input size plus the size of one block. | |
//That's why we need to add the size of one block here | |
size_t bufferSize = dataLength + kCCBlockSizeAES128; | |
void *buffer = malloc(bufferSize); | |
size_t numBytesDecrypted = 0; | |
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, | |
keyPtr, kCCKeySizeAES256, | |
NULL /* initialization vector (optional) */, | |
[self bytes], dataLength, /* input */ | |
buffer, bufferSize, /* output */ | |
&numBytesDecrypted); | |
if (cryptStatus == kCCSuccess) { | |
//the returned NSData takes ownership of the buffer and will free it on deallocation | |
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; | |
} | |
free(buffer); //free the buffer; | |
return nil; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment