Javascript AES加密不';不匹配iOS AES加密

Javascript AES加密不';不匹配iOS AES加密,javascript,objective-c,encryption,encoding,cryptojs,Javascript,Objective C,Encryption,Encoding,Cryptojs,我在iOS中加密一个NSString,这样编码和解码都很好: NSString *stringtoEncrypt = @"This string is to be encrypted"; NSString *key = @"12345678901234567890123456789012"; // Encode NSData *plain = [stringtoEncrypt dataUsingEncoding:NSUTF8StringEncoding]; NSData *cipher = [

我在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));

...
var text=“此字符串将被加密”;
var key=“123456789012134567890123456789012”;
变量iv='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00';
var encrypted=CryptoJS.AES.encrypt(文本,密钥,{iv:iv});
log(“Base64编码:+window.btoa(加密的密文));
但是,生成的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)

我倒是想用字符串来比较,但我猜这是在用它自己的方式把事情搞砸。加密是基于数据的,而不是基于字符的。转储必须是数据转储,这在脚本语言中稍微困难一些。非常感谢。我确实需要做些改变才能让它工作。我必须更改
CryptoJS.lib.WordArray([0,0,0,0])
to
CryptoJS.lib.WordArray.create([0,0,0,0])
还,
var encrypted=CryptoJS.AES.encrypt(文本,密钥,{iv:iv});console.log(“加密:”+加密)
似乎输出了我从iOS获得的相同的Base64字符串,甚至没有告诉它Base64编码,这似乎很奇怪。
CryptoJS.AES.encrypt()
结果不是WordArray,默认情况下使用OpenSSLFormatter。对其调用
toString()
,将其序列化为Base64格式。如果没有使用salt,那么它应该与
encrypted.ciphertext.toString(CryptoJS.enc.Base64)
匹配,但我认为也有例外。不太确定。谢谢你的解释