Javascript AES加密与iOS AES加密不匹配 [英] Javascript AES encryption doesn't match iOS AES encryption
问题描述
我正在加密iOS中的NSString
code> NSString * stringtoEncrypt = @此字符串要加密;
NSString * key = @12345678901234567890123456789012;
//编码
NSData * plain = [stringtoEncrypt dataUsingEncoding:NSUTF8StringEncoding];
NSData * cipher = [plain AES256EncryptWithKey:key];
NSString * cipherBase64 = [cipher base64EncodedString];
NSLog(@ciphered base64:%@,cipherBase64);
//解码
NSData * decipheredData = [cipherBase64 base64DecodedData];
NSString * decoded = [[NSString alloc] initWithData:[decipheredData AES256DecryptWithKey:key] encoding:NSUTF8StringEncoding];
NSLog(@%@,解码);
NSData扩展名:
- (NSData的*)AES256EncryptWithKey:(的NSString *)键
{
// '钥匙' 应该是AES256 32个字节,将空填充否则
炭keyPtr [kCCKeySizeAES256 + 1]; //用于终结器的空间(未使用)
bzero(keyPtr,sizeof(keyPtr)); //填充零(用于填充)
//获取密钥数据
[key getCString:keyPtr maxLength:sizeof(keyPtr)encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//查看文档:对于块密码,输出大小始终小于或等于输入大小加上一个块的大小。
//这就是为什么我们需要在这里添加一个块的大小
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void * buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,kCCAlgorithmAES128,kCCOptionPKCS7Padding,
keyPtr,kCCKeySizeAES256,
NULL / *初始化向量(可选)* /,
[自字节],数据长度,/ * input * /
buffer,bufferSize,/ * output * /
& numBytesEncrypted);
如果(cryptStatus == kCCSuccess){
//返回的NSData取缓冲器的所有权,将释放其上解除分配
返回[NSData的dataWithBytesNoCopy:缓冲区长度:numBytesEncrypted];
}
free(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 =此字符串要加密;
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]); //每个数字是一个32位的字b
通过调用 btoa()
在WordArray对象上,您强制将其绑定到字符串。为此使用默认的十六进制编码。之后 btoa()
将这个十六进制编码的字符串编码到Bas64中,这样会更加膨胀。
您可以直接编码一个WordArray into Base64:
encrypted.ciphertext.toString(CryptoJS.enc.Base64)
I am encrypting an NSString
in iOS like this which encodes and decodes fine:
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 extension:
- (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;
}
I can successfully pass the resulting Base64 string to Node.js
and have it decode the message. What I also need, is the same encoding method written in Javascript
.
Here is what I have so far:
<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));
However the resulting Base64 string does not match the one generated by iOS. Any ideas?
CryptoJS uses a password-based encryption compatible with OpenSSL when you pass a string as a key. Since you already have a full key and IV, you need to convert them into CryptoJS' native type which is a 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
By calling btoa()
on a WordArray object, you're forcing it to the stringified. The default hex-encoding is used for this. Afterwards btoa()
encodes this hex-encoded string into Bas64 which bloats it even more.
You can directly encode a WordArray into Base64:
encrypted.ciphertext.toString(CryptoJS.enc.Base64)
这篇关于Javascript AES加密与iOS AES加密不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!