-
-
Save demisang/716250080d77a7f65e66f4e813e5a636 to your computer and use it in GitHub Desktop.
import android.support.annotation.Nullable; | |
import android.util.Base64; | |
import java.nio.ByteBuffer; | |
import java.security.SecureRandom; | |
import javax.crypto.Cipher; | |
import javax.crypto.spec.IvParameterSpec; | |
import javax.crypto.spec.SecretKeySpec; | |
/** | |
* AesCipher | |
* <p>Encode/Decode text by password using AES-128-CBC algorithm</p> | |
*/ | |
public class AesCipher { | |
public static final int INIT_VECTOR_LENGTH = 16; | |
/** | |
* @see <a href="https://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to-a-hex-string-in-java">how-to-convert-a-byte-array-to-a-hex-string</a> | |
*/ | |
private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); | |
/** | |
* Encoded/Decoded data | |
*/ | |
protected String data; | |
/** | |
* Initialization vector value | |
*/ | |
protected String initVector; | |
/** | |
* Error message if operation failed | |
*/ | |
protected String errorMessage; | |
private AesCipher() { | |
super(); | |
} | |
/** | |
* AesCipher constructor. | |
* | |
* @param initVector Initialization vector value | |
* @param data Encoded/Decoded data | |
* @param errorMessage Error message if operation failed | |
*/ | |
private AesCipher(@Nullable String initVector, @Nullable String data, @Nullable String errorMessage) { | |
super(); | |
this.initVector = initVector; | |
this.data = data; | |
this.errorMessage = errorMessage; | |
} | |
/** | |
* Encrypt input text by AES-128-CBC algorithm | |
* | |
* @param secretKey 16/24/32 -characters secret password | |
* @param plainText Text for encryption | |
* @return Encoded string or NULL if error | |
*/ | |
public static AesCipher encrypt(String secretKey, String plainText) { | |
String initVector = null; | |
try { | |
// Check secret length | |
if (!isKeyLengthValid(secretKey)) { | |
throw new Exception("Secret key's length must be 128, 192 or 256 bits"); | |
} | |
// Get random initialization vector | |
SecureRandom secureRandom = new SecureRandom(); | |
byte[] initVectorBytes = new byte[INIT_VECTOR_LENGTH / 2]; | |
secureRandom.nextBytes(initVectorBytes); | |
initVector = bytesToHex(initVectorBytes); | |
initVectorBytes = initVector.getBytes("UTF-8"); | |
IvParameterSpec ivParameterSpec = new IvParameterSpec(initVectorBytes); | |
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES"); | |
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); | |
// Encrypt input text | |
byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8")); | |
ByteBuffer byteBuffer = ByteBuffer.allocate(initVectorBytes.length + encrypted.length); | |
byteBuffer.put(initVectorBytes); | |
byteBuffer.put(encrypted); | |
// Result is base64-encoded string: initVector + encrypted result | |
String result = Base64.encodeToString(byteBuffer.array(), Base64.DEFAULT); | |
// Return successful encoded object | |
return new AesCipher(initVector, result, null); | |
} catch (Throwable t) { | |
t.printStackTrace(); | |
// Operation failed | |
return new AesCipher(initVector, null, t.getMessage()); | |
} | |
} | |
/** | |
* Decrypt encoded text by AES-128-CBC algorithm | |
* | |
* @param secretKey 16/24/32 -characters secret password | |
* @param cipherText Encrypted text | |
* @return Self object instance with data or error message | |
*/ | |
public static AesCipher decrypt(String secretKey, String cipherText) { | |
try { | |
// Check secret length | |
if (!isKeyLengthValid(secretKey)) { | |
throw new Exception("Secret key's length must be 128, 192 or 256 bits"); | |
} | |
// Get raw encoded data | |
byte[] encrypted = Base64.decode(cipherText, Base64.DEFAULT); | |
// Slice initialization vector | |
IvParameterSpec ivParameterSpec = new IvParameterSpec(encrypted, 0, INIT_VECTOR_LENGTH); | |
// Set secret password | |
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES"); | |
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); | |
// Trying to get decrypted text | |
String result = new String(cipher.doFinal(encrypted, INIT_VECTOR_LENGTH, encrypted.length - INIT_VECTOR_LENGTH)); | |
// Return successful decoded object | |
return new AesCipher(bytesToHex(ivParameterSpec.getIV()), result, null); | |
} catch (Throwable t) { | |
t.printStackTrace(); | |
// Operation failed | |
return new AesCipher(null, null, t.getMessage()); | |
} | |
} | |
/** | |
* Check that secret password length is valid | |
* | |
* @param key 16/24/32 -characters secret password | |
* @return TRUE if valid, FALSE otherwise | |
*/ | |
public static boolean isKeyLengthValid(String key) { | |
return key.length() == 16 || key.length() == 24 || key.length() == 32; | |
} | |
/** | |
* Convert Bytes to HEX | |
* | |
* @param bytes Bytes array | |
* @return String with bytes values | |
*/ | |
public static String bytesToHex(byte[] bytes) { | |
char[] hexChars = new char[bytes.length * 2]; | |
for (int j = 0; j < bytes.length; j++) { | |
int v = bytes[j] & 0xFF; | |
hexChars[j * 2] = hexArray[v >>> 4]; | |
hexChars[j * 2 + 1] = hexArray[v & 0x0F]; | |
} | |
return new String(hexChars); | |
} | |
/** | |
* Get encoded/decoded data | |
*/ | |
public String getData() { | |
return data; | |
} | |
/** | |
* Get initialization vector value | |
*/ | |
public String getInitVector() { | |
return initVector; | |
} | |
/** | |
* Get error message | |
*/ | |
public String getErrorMessage() { | |
return errorMessage; | |
} | |
/** | |
* Check that operation failed | |
* | |
* @return TRUE if failed, FALSE otherwise | |
*/ | |
public boolean hasError() { | |
return this.errorMessage != null; | |
} | |
/** | |
* To string return resulting data | |
* | |
* @return Encoded/decoded data | |
*/ | |
public String toString() { | |
return getData(); | |
} | |
} | |
// USAGE | |
String secretKey = "26kozQaKwRuNJ24t"; | |
String text = "Some text"; | |
AesCipher encrypted = AesCipher.encrypt(secretKey, text); | |
AesCipher decrypted = AesCipher.decrypt(secretKey, encrypted); | |
encrypted.hasError(); // TRUE if operation failed, FALSE otherwise | |
encrypted.getData(); // Encoded/Decoded result | |
encrypted.getInitVector(); // Get used (random if encode) init vector | |
// decrypted.* has identical methods |
<?php | |
/** | |
* AesCipher | |
* | |
* Encode/Decode text by password using AES-128-CBC algorithm | |
*/ | |
class AesCipher | |
{ | |
const CIPHER = 'AES-128-CBC'; | |
const INIT_VECTOR_LENGTH = 16; | |
/** | |
* Encoded/Decoded data | |
* | |
* @var null|string | |
*/ | |
protected $data; | |
/** | |
* Initialization vector value | |
* | |
* @var string | |
*/ | |
protected $initVector; | |
/** | |
* Error message if operation failed | |
* | |
* @var null|string | |
*/ | |
protected $errorMessage; | |
/** | |
* AesCipher constructor. | |
* | |
* @param string $initVector Initialization vector value | |
* @param string|null $data Encoded/Decoded data | |
* @param string|null $errorMessage Error message if operation failed | |
*/ | |
public function __construct($initVector, $data = null, $errorMessage = null) | |
{ | |
$this->initVector = $initVector; | |
$this->data = $data; | |
$this->errorMessage = $errorMessage; | |
} | |
/** | |
* Encrypt input text by AES-128-CBC algorithm | |
* | |
* @param string $secretKey 16/24/32 -characters secret password | |
* @param string $plainText Text for encryption | |
* | |
* @return self Self object instance with data or error message | |
*/ | |
public static function encrypt($secretKey, $plainText) | |
{ | |
try { | |
// Check secret length | |
if (!static::isKeyLengthValid($secretKey)) { | |
throw new \InvalidArgumentException("Secret key's length must be 128, 192 or 256 bits"); | |
} | |
// Get random initialization vector | |
$initVector = bin2hex(openssl_random_pseudo_bytes(static::INIT_VECTOR_LENGTH / 2)); | |
// Encrypt input text | |
$raw = openssl_encrypt( | |
$plainText, | |
static::CIPHER, | |
$secretKey, | |
OPENSSL_RAW_DATA, | |
$initVector | |
); | |
// Return base64-encoded string: initVector + encrypted result | |
$result = base64_encode($initVector . $raw); | |
if ($result === false) { | |
// Operation failed | |
return new static($initVector, null, openssl_error_string()); | |
} | |
// Return successful encoded object | |
return new static($initVector, $result); | |
} catch (\Exception $e) { | |
// Operation failed | |
return new static(isset($initVector), null, $e->getMessage()); | |
} | |
} | |
/** | |
* Decrypt encoded text by AES-128-CBC algorithm | |
* | |
* @param string $secretKey 16/24/32 -characters secret password | |
* @param string $cipherText Encrypted text | |
* | |
* @return self Self object instance with data or error message | |
*/ | |
public static function decrypt($secretKey, $cipherText) | |
{ | |
try { | |
// Check secret length | |
if (!static::isKeyLengthValid($secretKey)) { | |
throw new \InvalidArgumentException("Secret key's length must be 128, 192 or 256 bits"); | |
} | |
// Get raw encoded data | |
$encoded = base64_decode($cipherText); | |
// Slice initialization vector | |
$initVector = substr($encoded, 0, static::INIT_VECTOR_LENGTH); | |
// Slice encoded data | |
$data = substr($encoded, static::INIT_VECTOR_LENGTH); | |
// Trying to get decrypted text | |
$decoded = openssl_decrypt( | |
$data, | |
static::CIPHER, | |
$secretKey, | |
OPENSSL_RAW_DATA, | |
$initVector | |
); | |
if ($decoded === false) { | |
// Operation failed | |
return new static(isset($initVector), null, openssl_error_string()); | |
} | |
// Return successful decoded object | |
return new static($initVector, $decoded); | |
} catch (\Exception $e) { | |
// Operation failed | |
return new static(isset($initVector), null, $e->getMessage()); | |
} | |
} | |
/** | |
* Check that secret password length is valid | |
* | |
* @param string $secretKey 16/24/32 -characters secret password | |
* | |
* @return bool | |
*/ | |
public static function isKeyLengthValid($secretKey) | |
{ | |
$length = strlen($secretKey); | |
return $length == 16 || $length == 24 || $length == 32; | |
} | |
/** | |
* Get encoded/decoded data | |
* | |
* @return string|null | |
*/ | |
public function getData() | |
{ | |
return $this->data; | |
} | |
/** | |
* Get initialization vector value | |
* | |
* @return string|null | |
*/ | |
public function getInitVector() | |
{ | |
return $this->initVector; | |
} | |
/** | |
* Get error message | |
* | |
* @return string|null | |
*/ | |
public function getErrorMessage() | |
{ | |
return $this->errorMessage; | |
} | |
/** | |
* Check that operation failed | |
* | |
* @return bool | |
*/ | |
public function hasError() | |
{ | |
return $this->errorMessage !== null; | |
} | |
/** | |
* To string return resulting data | |
* | |
* @return null|string | |
*/ | |
public function __toString() | |
{ | |
return $this->getData(); | |
} | |
} | |
// USAGE | |
$secretKey = '26kozQaKwRuNJ24t'; | |
$text = 'Some text'; | |
$encrypted = AesCipher::encrypt($secretKey, $text); | |
$decrypted = AesCipher::decrypt($secretKey, $encrypted); | |
$encrypted->hasError(); // TRUE if operation failed, FALSE otherwise | |
$encrypted->getData(); // Encoded/Decoded result | |
$encrypted->getInitVector(); // Get used (random if encode) init vector | |
// $decrypted->* has identical methods |
Thank you for useful example. I have been searching for exactly this solution (PHP on server-side + java for mobile side). I tried to include your nice code in my project and found a tiny mistake.
Please change this code
AesCipher encrypted = AesCipher.encrypt(secretKey, text);
AesCipher decrypted = AesCipher.decrypt(secretKey, encrypted);
to
AesCipher encrypted = AesCipher.encrypt(secretKey, text);
AesCipher decrypted = AesCipher.decrypt(secretKey, encrypted.getData());
in USAGE description for Java code.
Thank you bro!
Hi, I tried to decrypt php, when encrypted in java. but its not working in php code
For iOS Code:
===========
import Foundation
import CommonCrypto
extension String {
func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = self.data(using: String.Encoding.utf8),
let cryptData = NSMutableData(length: Int((data.count)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
(data as NSData).bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if cryptStatus == kCCSuccess {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString
}
else {
return nil
}
}
return nil
}
func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = NSData(base64Encoded: self, options: .ignoreUnknownCharacters),
let cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if cryptStatus == kCCSuccess {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData as Data, encoding:String.Encoding.utf8)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
}
let messgeBody = "Test message"
let AES_KEY = "Your AES KEY"
let AES_IV = "Your AES IV"
let encryptedMsg = messgeBody.aesEncrypt(key: AES_KEY, iv: AES_IV)
print(encryptedMsg!)
let decryptMsg = encryptedMsg?.aesDecrypt(key: AES_KEY, iv: AES_IV)
print(decryptMsg!)
Generate Dynamic AES_IV in iOS:
//
// AESEncryption.swift
// Created by Brahmam Mannam on 6/24/19.
//
import Foundation
import CommonCrypto
protocol Cryptable {
func encrypt(_ string: String) throws -> Data
func decrypt(_ data: Data) throws -> String
}
struct AES {
private let key: Data
private let ivSize: Int = kCCBlockSizeAES128
private let options: CCOptions = CCOptions(kCCOptionPKCS7Padding)
init(keyString: String) throws {
// guard keyString.count == kCCKeySizeAES256 else {
// throw Error.invalidKeySize
// }
self.key = Data(keyString.utf8)
}
}
extension AES {
enum Error: Swift.Error {
case invalidKeySize
case generateRandomIVFailed
case encryptionFailed
case decryptionFailed
case dataToStringFailed
}
}
private extension AES {
func generateRandomIV(for data: inout Data) throws {
try data.withUnsafeMutableBytes { dataBytes in
guard let dataBytesBaseAddress = dataBytes.baseAddress else {
throw Error.generateRandomIVFailed
}
let status: Int32 = SecRandomCopyBytes(
kSecRandomDefault,
kCCBlockSizeAES128,
dataBytesBaseAddress
)
guard status == 0 else {
throw Error.generateRandomIVFailed
}
}
}
}
extension AES: Cryptable {
func encrypt(_ string: String) throws -> Data {
let dataToEncrypt = Data(string.utf8)
let bufferSize: Int = ivSize + dataToEncrypt.count + kCCBlockSizeAES128
var buffer = Data(count: bufferSize)
try generateRandomIV(for: &buffer)
var numberBytesEncrypted: Int = 0
do {
try key.withUnsafeBytes { keyBytes in
try dataToEncrypt.withUnsafeBytes { dataToEncryptBytes in
try buffer.withUnsafeMutableBytes { bufferBytes in
guard let keyBytesBaseAddress = keyBytes.baseAddress,
let dataToEncryptBytesBaseAddress = dataToEncryptBytes.baseAddress,
let bufferBytesBaseAddress = bufferBytes.baseAddress else {
throw Error.encryptionFailed
}
let cryptStatus: CCCryptorStatus = CCCrypt( // Stateless, one-shot encrypt operation
CCOperation(kCCEncrypt), // op: CCOperation
CCAlgorithm(kCCAlgorithmAES), // alg: CCAlgorithm
options, // options: CCOptions
keyBytesBaseAddress, // key: the "password"
key.count, // keyLength: the "password" size
bufferBytesBaseAddress, // iv: Initialization Vector
dataToEncryptBytesBaseAddress, // dataIn: Data to encrypt bytes
dataToEncryptBytes.count, // dataInLength: Data to encrypt size
bufferBytesBaseAddress + ivSize, // dataOut: encrypted Data buffer
bufferSize, // dataOutAvailable: encrypted Data buffer size
&numberBytesEncrypted // dataOutMoved: the number of bytes written
)
guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
throw Error.encryptionFailed
}
}
}
}
} catch {
throw Error.encryptionFailed
}
let encryptedData: Data = buffer[..<(numberBytesEncrypted + ivSize)]
return encryptedData
}
func decrypt(_ data: Data) throws -> String {
let bufferSize: Int = data.count - ivSize
var buffer = Data(count: bufferSize)
var numberBytesDecrypted: Int = 0
do {
try key.withUnsafeBytes { keyBytes in
try data.withUnsafeBytes { dataToDecryptBytes in
try buffer.withUnsafeMutableBytes { bufferBytes in
guard let keyBytesBaseAddress = keyBytes.baseAddress,
let dataToDecryptBytesBaseAddress = dataToDecryptBytes.baseAddress,
let bufferBytesBaseAddress = bufferBytes.baseAddress else {
throw Error.encryptionFailed
}
let cryptStatus: CCCryptorStatus = CCCrypt( // Stateless, one-shot encrypt operation
CCOperation(kCCDecrypt), // op: CCOperation
CCAlgorithm(kCCAlgorithmAES128), // alg: CCAlgorithm
options, // options: CCOptions
keyBytesBaseAddress, // key: the "password"
key.count, // keyLength: the "password" size
dataToDecryptBytesBaseAddress, // iv: Initialization Vector
dataToDecryptBytesBaseAddress + ivSize, // dataIn: Data to decrypt bytes
bufferSize, // dataInLength: Data to decrypt size
bufferBytesBaseAddress, // dataOut: decrypted Data buffer
bufferSize, // dataOutAvailable: decrypted Data buffer size
&numberBytesDecrypted // dataOutMoved: the number of bytes written
)
guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
throw Error.decryptionFailed
}
}
}
}
} catch {
throw Error.encryptionFailed
}
let decryptedData: Data = buffer[..<numberBytesDecrypted]
guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
throw Error.dataToStringFailed
}
return decryptedString
}
}
**How To Use:
To Encrypt Your String:
**************************
let messgeBody = "Your Message Here"
do {
let aes = try AES(keyString: aes128_key) //aes128_key = "Your AES_KEY"
let encryptedData: Data = try aes.encrypt(messgeBody)
let encryptedMsgStr : String = encryptedData.base64EncodedString()
print(encryptedMsgStr)
} catch {
print("Something went wrong: \(error)")
}
To Decrypt:
*************
var messageData = NSData()
messageData = NSData(base64Encoded: "encrypted message string here..", options: [])!
do {
let aes = try AES(keyString: aes128_key) //aes128_key = "Your AES_KEY"
let decryptedMessageStr: String = try aes.decrypt(messageData as Data)
print(decryptedMessageStr)
} catch {
print("Something went wrong: \(error)")
}
It still doesnt work after i changed CIPHER = 'AES-128-CBC' to CIPHER = 'AES-256-CBC' and IVlength t0 32.Can you please suggest a solution?
my php decrypt code :
$key = "Cw3eLYMOXslhAg5iK4N36khd/NdjIX70WOzzJmb4DCU="
list($encrypted, $iv) = explode('::', base64_decode($cipherStr), 2);
$result = openssl_decrypt($encrypted, "AES-128-CBC", base64_decode($key), 0, $iv);
it work!
but my java decrypt code :
byte[] cipherBytes = Base64Utils.decodeFromString(test);
byte[] iv = Arrays.copyOfRange(cipherBytes, 130, 146);
byte[] content = Arrays.copyOfRange(cipherBytes, 0, 128);
byte[] key = Base64Utils.decodeFromString("Cw3eLYMOXslhAg5iK4N36khd/NdjIX70WOzzJmb4DCU=");
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv, 0, cipher.getBlockSize());
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
String result = new String(cipher.doFinal(content));
It still doesnt work 。 i cant change the encrypt code
Please help me to solve this
hi sir i want this code in angular.
Hi. Is there a swift equivalent to above provided Java Decrypt Function?
public static AesCipher decrypt(String secretKey, String cipherText) {
try {
// Check secret length
if (!isKeyLengthValid(secretKey)) {
throw new Exception("Secret key's length must be 128, 192 or 256 bits");
}
// Get raw encoded data
byte[] encrypted = Base64.decode(cipherText, Base64.DEFAULT);
// Slice initialization vector
IvParameterSpec ivParameterSpec = new IvParameterSpec(encrypted, 0, INIT_VECTOR_LENGTH);
// Set secret password
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
// Trying to get decrypted text
String result = new String(cipher.doFinal(encrypted, INIT_VECTOR_LENGTH, encrypted.length - INIT_VECTOR_LENGTH));
// Return successful decoded object
return new AesCipher(bytesToHex(ivParameterSpec.getIV()), result, null);
} catch (Throwable t) {
t.printStackTrace();
// Operation failed
return new AesCipher(null, null, t.getMessage());
}
}
my php decrypt code :
$key = "Cw3eLYMOXslhAg5iK4N36khd/NdjIX70WOzzJmb4DCU=" list($encrypted, $iv) = explode('::', base64_decode($cipherStr), 2); $result = openssl_decrypt($encrypted, "AES-128-CBC", base64_decode($key), 0, $iv);
it work!
but my java decrypt code :
byte[] cipherBytes = Base64Utils.decodeFromString(test); byte[] iv = Arrays.copyOfRange(cipherBytes, 130, 146); byte[] content = Arrays.copyOfRange(cipherBytes, 0, 128); byte[] key = Base64Utils.decodeFromString("Cw3eLYMOXslhAg5iK4N36khd/NdjIX70WOzzJmb4DCU="); Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv, 0, cipher.getBlockSize()); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); String result = new String(cipher.doFinal(content));
It still doesnt work 。 i cant change the encrypt code
Please help me to solve this
Hello, I also encountered such a problem. Have you solved it?
How to encrypt and decrypt above example in javascript?
Thank you so much.
for IOS?