用iOS加密;用.net解密
本文关键字:解密 net 加密 iOS | 更新日期: 2023-09-27 17:53:29
我需要在iPhone或iPad上加密字符串(实际上是XML文件),然后用。net应用程序解密它。感谢David Veksler的问题,.Net和iPhone之间的AES互操作性?,和博客文章在这里,http://automagical.rationalmind.net/2009/02/12/aes-interoperability-between-net-and-iphone/,我想我是相当接近完成这个。
但是在c#方法返回的解密字符串(XML)中,前16个字符是乱码。从第17个字符开始,解密的字符串与objective-c方法加密的字符串匹配。
我尽可能严格地遵循David的代码,但可能在一些尝试和错误之后改变了一些东西。这里是加密代码(密码和initVector只是硬编码在那里现在):
CCCryptorStatus result = CCCryptorCreate(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding, // 0x0000 or kCCOptionPKCS7Padding
(const void *)[@"1234567891123456" dataUsingEncoding:NSUTF8StringEncoding].bytes,
[@"1234567891123456" dataUsingEncoding:NSUTF8StringEncoding].length,
(const void *)[@"0000000000000000" dataUsingEncoding:NSUTF8StringEncoding].bytes,
&thisEncipher
);
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t remainingBytes = 0;
size_t movedBytes = 0;
size_t plainTextBufferSize = 0;
size_t totalBytesWritten = 0;
uint8_t *ptr;
NSData *plainText = [xmlFileText dataUsingEncoding:NSASCIIStringEncoding];
plainTextBufferSize = [plainText length];
bufferPtrSize = CCCryptorGetOutputLength(thisEncipher, plainTextBufferSize, true);
bufferPtr = malloc(bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
ptr = bufferPtr;
remainingBytes = bufferPtrSize;
result = CCCryptorUpdate(thisEncipher,
(const void *)[plainText bytes],
plainTextBufferSize,
ptr,
remainingBytes,
&movedBytes
);
ptr += movedBytes;
remainingBytes -= movedBytes;
totalBytesWritten += movedBytes;
result = CCCryptorFinal(thisEncipher,
ptr,
remainingBytes,
&movedBytes
);
totalBytesWritten += movedBytes;
if (thisEncipher)
{
(void) CCCryptorRelease(thisEncipher);
thisEncipher = NULL;
}
if (result == kCCSuccess)
{
NSData *encryptedData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)totalBytesWritten];
[[encryptedData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn] writeToFile:docFile atomically:NO encoding:NSUTF8StringEncoding error:nil];
NSLog(@"%d:%d:%d:%@:%@", xmlFileText.length,
encryptedData.length,
[encryptedData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn].length,
encryptedData,
[encryptedData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]);
if (bufferPtr)
free(bufferPtr);
return;
}
下面是解密代码:
public static string DecryptString(string base64StringToDecrypt, string passphrase)
{
//Set up the encryption objects
using (AesCryptoServiceProvider acsp = GetProvider(Encoding.Default.GetBytes(passphrase)))
{
byte[] RawBytes = Convert.FromBase64String(base64StringToDecrypt);
ICryptoTransform ictD = acsp.CreateDecryptor();
//RawBytes now contains original byte array, still in Encrypted state
//Decrypt into stream
MemoryStream msD = new MemoryStream(RawBytes, 0, RawBytes.Length);
CryptoStream csD = new CryptoStream(msD, ictD, CryptoStreamMode.Read);
//csD now contains original byte array, fully decrypted
//return the content of msD as a regular string
return (new StreamReader(csD)).ReadToEnd();
}
}
从现场比较几个,它似乎NSData, encryptedData包含相同的值作为byte[]
, RawBytes。但是在StreamReader.ReadToEnd()
之后返回的XML字符串与NSString
、xmlFileText
匹配,除了前16个字符。我怀疑问题是我加密获得NSData
*encryptedData的方式,或者我将其转换为base64编码的字符串并将其写入文件的方式,或者我解密byte[]
RawBytes的方式,或者我将解密的csD转换回字符串的方式。如果有人能指出我的错误,我会很感激的。
更新:在David的评论之后,我正在仔细研究IV.我现在正试图使用16个零。
在iOS上,我使用:
(const void *)[@"0000000000000000" dataUsingEncoding:NSUTF8StringEncoding].bytes
在。net上我使用:
new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
如果您的消息只有第一部分是乱码,那么很可能您的IV(初始化向量)在加密和解密端不相同。IV会影响第一个数据块,所以错误的IV会导致第一个数据块错误,而其余的数据块是正确的,这是有道理的。
在代码的一端,使用"0"字符的字符串作为IV。在另一端,使用由0值字节组成的字节数组作为IV。它们是不一样的;'0'字符不一定是0字节值。