我正在尝试使用 AES 解密来解密 Base64Encoded String 消息。
加密消息(Base64Encoded 字符串): tNC6umcfBS/gelbo2VJF3i4LAhUKMp4oDHWN5KyYUTWeJIQKKYx6oAcQnGncIrPJNC1tUYMKV4kJQj3q9voIOrxc1n7FmRFvDXeRgWGNcGYO66dH3VjoEgF0oxZOpfzwSZKSv3Jm7Q=
密码(字符串) =“SOMEPASSWORDSTRING”
解密消息的步骤:
数据必须从 base 64 解码为普通字符串。
从输入中提取 IV 和加密文本
使用 IV 和相同的密码生成用于加密文本的密钥。密钥生成应遵循与以下相同的步骤。
生成 PBE 密钥(256 位)
a. Specs created with passphrase and IV as salt, 62233 as iteration count b. Used PBKDF2WithHmacSHA256 to generate a secret factory because it's appropriate for turning passwords into keys. c. This key is further encoded and converted to another key with AES encryption.
使用生成的密钥和 IV,以与以下完全相同的方式初始化密码
此密钥初始化密码对象
a. Used AES in GCM, GCM specs are prepared using tag size of 128 bits and the IV b. Cipher object is initialized using AES/GCM/PKCS5Padding. c. Based on operational mode the cipher is initialized with op mode(encryption), secret key and GCM params.
生成密码以从加密文本中获取消息。
下面是用于解密输入消息的 JAVA 代码
public class Decryption {
private static final String KEY_GENERATING_ALGO = "PBKDF2WithHmacSHA256";
private static final String ENCRYPTION = "AES";
private static final String TRANSFORMATION_ALGORITHM= "AES/GCM/PKCS5Padding";
private static final int KEY_SIZE_BITS = 256;
private static final int TAG_SIZE_BITS = 128;
private static final int ITERATION_COUNT = 62233;
// Use following sample data to test the decryption-
//tNC6umcfBS/gelbo2VJF3i4LAhUKMp4oDHWN5KyYUTWeJIQKKYx6oAcQnGncIrPJNC1tUYMKV4kJQj3q9voIOrxc1n7FmRFvDXeRgWGNcGYO66dH3VjoEgF0oxZOpfzwSZKSv3Jm7Q==
// This key has is base 64 encoded with IV prepended with encrypted text
public Cipher initCipher(int encryptMode, String password, byte[] iv) throws InvalidKeySpecException {
try {
GCMParameterSpec gcmparams = new GCMParameterSpec(TAG_SIZE_BITS, iv);
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), iv, ITERATION_COUNT, KEY_SIZE_BITS);
SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_GENERATING_ALGO);
SecretKey pbeKey = factory.generateSecret(pbeKeySpec);
byte[] keyBytes = pbeKey.getEncoded();
SecretKey key = new SecretKeySpec(keyBytes, ENCRYPTION);
Cipher cipher = Cipher.getInstance(TRANSFORMATION_ALGORITHM);
cipher.init(encryptMode, key, gcmparams);
return cipher;
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| InvalidAlgorithmParameterException | InvalidKeySpecException ex) {
throw new AssertionError(ex);
}
}
//Decryption Algo
public String decrypt(String encrypted){
byte[] decFeeder = Base64.getDecoder().decode(encrypted);
String key = "someKey"; // A new key will be provided by APIF through a secure channel
char[] password = key.toCharArray();
try {
byte[] iv = Arrays.copyOfRange(decFeeder, 0, 32);
byte[] ciphertext = Arrays.copyOfRange(decFeeder, iv.length, decFeeder.length);
Cipher cipher = initCipher(Cipher.DECRYPT_MODE, key, iv);
byte[] message = cipher.doFinal(ciphertext);
String decrypted = new String(message);
return decrypted;
} catch (IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException ex) {
throw new AssertionError(ex);
}
}
}
我在 Swift 中使用下面的代码来生成与上面的 JAVA 代码相同的代码,但是我无法解密消息/密文。
func aesDecrypt(encryptedData: Data, password: String) -> Data? {
let iv = Array([UInt8](encryptedData)[0 ..< 33])
let ivData = Data(iv)
let encryptedCipher = [UInt8](encryptedData)[iv.count ..< encryptedData.count]
let encryptedCipherData = Data(encryptedCipher)
let passwordKey = createKey(password:Data(password.utf8) , salt: ivData)
var decryptSuccess = false
let size = (encryptedCipher.count) + kCCBlockSizeAES128
var clearTextData = Data.init(count: size)
var numberOfBytesDecrypted : size_t = 0
let cryptStatus = ivData.withUnsafeBytes {ivBytes in
clearTextData.withUnsafeMutableBytes {clearTextBytes in
encryptedCipherData.withUnsafeBytes {encryptedBytes in
passwordKey.withUnsafeBytes {keyBytes in
CCCrypt(CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
CCOptions(kCCOptionPKCS7Padding),
keyBytes,
passwordKey.count,
ivBytes,
encryptedBytes,
(encryptedCipher.count),
clearTextBytes,
size,
&numberOfBytesDecrypted)
}
}
}
}
if cryptStatus == Int32(kCCSuccess)
{
clearTextData.count = numberOfBytesDecrypted
debugPrint(clearTextData)
decryptSuccess = true
}
return decryptSuccess ? clearTextData : Data.init(count: 0)
}
func createKey(password: Data, salt: Data) -> Data? {
let length = kCCKeySizeAES256
var status = Int32(0)
var derivedBytes = [UInt8](repeating: 0, count: length)
password.withUnsafeBytes { (passwordBytes: UnsafePointer<Int8>!) in
salt.withUnsafeBytes { (saltBytes: UnsafePointer<UInt8>!) in
status = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2), // algorithm
passwordBytes, // password
password.count, // passwordLen
saltBytes, // salt
salt.count, // saltLen
UInt32(kCCPRFHmacAlgSHA256), // prf
UInt32(62233), // rounds
&derivedBytes, // derivedKey
length) // derivedKeyLen
}
}
guard status == 0 else {
return nil
}
return Data(bytes: UnsafePointer<UInt8>(derivedBytes), count: length)
}
用法:
guard let encryptedData = Data(base64Encoded: input) else{
return nil
}
let decryptData = aesDecrypt3(encryptedData: encryptedData)
let decryptedMessage = String(data: decryptData, encoding: .utf8) ?? "Unable to Decrypt"
任何线索将不胜感激,我想知道我在尝试快速转换时是否缺少一些配置或数据转换。