Javascript AES 加密与 iOS AES 加密不匹配
Javascript AES encryption doesn't match iOS AES encryption
我正在 iOS 中加密一个 NSString
,这样编码和解码都很好:
NSString *stringtoEncrypt = @"This string is to be encrypted";
NSString *key = @"12345678901234567890123456789012";
// Encode
NSData *plain = [stringtoEncrypt dataUsingEncoding:NSUTF8StringEncoding];
NSData *cipher = [plain AES256EncryptWithKey:key];
NSString *cipherBase64 = [cipher base64EncodedString];
NSLog(@"ciphered base64: %@", cipherBase64);
// Decode
NSData *decipheredData = [cipherBase64 base64DecodedData];
NSString *decoded = [[NSString alloc] initWithData:[decipheredData AES256DecryptWithKey:key] encoding:NSUTF8StringEncoding];
NSLog(@"%@", decoded);
NSData 扩展名:
- (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;
}
我可以成功地将生成的 Base64 字符串传递给 Node.js
并让它解码消息。我还需要的,是写在Javascript
中的同样的编码方式。
这是我目前所拥有的:
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
...
var text = "This string is to be encrypted";
var key = "12345678901234567890123456789012";
var iv = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00';
var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv});
console.log("Base64 encoded: " + window.btoa(encrypted.ciphertext));
然而,生成的 Base64 字符串与 iOS 生成的字符串不匹配。
有什么想法吗?
当您将字符串作为密钥传递时,CryptoJS 使用与 OpenSSL 兼容的基于密码的加密。由于您已经拥有完整的密钥和 IV,因此您需要将它们转换为 CryptoJS 的原生类型,即 WordArray:
var key = CryptoJS.enc.Utf8.parse("12345678901234567890123456789012");
var iv = CryptoJS.lib.WordArray.create([0, 0, 0, 0]); // each number is a word of 32 bit
通过在 WordArray 对象上调用 btoa()
,您可以强制将其字符串化。为此使用默认的十六进制编码。之后 btoa()
将这个十六进制编码的字符串编码为 Bas64,这使它更加膨胀。
您可以直接将 WordArray 编码为 Base64:
encrypted.ciphertext.toString(CryptoJS.enc.Base64)
我正在 iOS 中加密一个 NSString
,这样编码和解码都很好:
NSString *stringtoEncrypt = @"This string is to be encrypted";
NSString *key = @"12345678901234567890123456789012";
// Encode
NSData *plain = [stringtoEncrypt dataUsingEncoding:NSUTF8StringEncoding];
NSData *cipher = [plain AES256EncryptWithKey:key];
NSString *cipherBase64 = [cipher base64EncodedString];
NSLog(@"ciphered base64: %@", cipherBase64);
// Decode
NSData *decipheredData = [cipherBase64 base64DecodedData];
NSString *decoded = [[NSString alloc] initWithData:[decipheredData AES256DecryptWithKey:key] encoding:NSUTF8StringEncoding];
NSLog(@"%@", decoded);
NSData 扩展名:
- (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;
}
我可以成功地将生成的 Base64 字符串传递给 Node.js
并让它解码消息。我还需要的,是写在Javascript
中的同样的编码方式。
这是我目前所拥有的:
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
...
var text = "This string is to be encrypted";
var key = "12345678901234567890123456789012";
var iv = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00';
var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv});
console.log("Base64 encoded: " + window.btoa(encrypted.ciphertext));
然而,生成的 Base64 字符串与 iOS 生成的字符串不匹配。 有什么想法吗?
当您将字符串作为密钥传递时,CryptoJS 使用与 OpenSSL 兼容的基于密码的加密。由于您已经拥有完整的密钥和 IV,因此您需要将它们转换为 CryptoJS 的原生类型,即 WordArray:
var key = CryptoJS.enc.Utf8.parse("12345678901234567890123456789012");
var iv = CryptoJS.lib.WordArray.create([0, 0, 0, 0]); // each number is a word of 32 bit
通过在 WordArray 对象上调用 btoa()
,您可以强制将其字符串化。为此使用默认的十六进制编码。之后 btoa()
将这个十六进制编码的字符串编码为 Bas64,这使它更加膨胀。
您可以直接将 WordArray 编码为 Base64:
encrypted.ciphertext.toString(CryptoJS.enc.Base64)