2012-09-28 49 views
2

我想在iOS上使用CES模式加密使用3DES加密NSString。3DES加密CBC模式在目标c

相同的加密方法正在ASP.NET上使用,他们正在使用的加密字符串与web服务一起工作。从.NET代码获得的woodcraft554的加密字符串是:9SWzd+rlvu/tK5UZoCXt8Q==

.NET使用零填充进行加密。我使用的代码是:

+(NSString*)new3DESwithoperand:(NSString*)plaintext encryptOrDecrypt:(CCOperation)encryptorDecrypt key:(NSString*)key initVec:(NSString*)initVec 
{  

NSData* data = [plaintext dataUsingEncoding:NSUTF8StringEncoding]; 
const void *vplainText = [data bytes];; 
size_t plainTextBufferSize = [data length]; 
NSLog(@"%@, Length: %u",[data description],[data length]); 

size_t bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1); 
NSLog(@"%zu, sizof of uint8_t: %zu",bufferPtrSize, sizeof(uint8_t)); 
size_t movedBytes = 0; 
uint8_t *bufferPtr = malloc(bufferPtrSize * sizeof(uint8_t)); 
NSLog(@"%zu",sizeof(bufferPtr)); 
memset((void*)bufferPtr, 0x0, bufferPtrSize); 
NSLog(@"%zu",sizeof(bufferPtr)); 
// memset((void *)initVec, 0x0, (size_t) sizeof(initVec)); 
const void * vkey = [[NSString base64DataFromString:key] bytes]; 
const void *vinitVec = [[NSString base64DataFromString:initVec] bytes]; 
NSLog(@"vinitvec: %@",[[NSString base64DataFromString:initVec] description]); 

CCCryptorStatus ccStatus; 
ccStatus = CCCrypt(encryptorDecrypt, 
        kCCAlgorithm3DES, 
        kCCOptionPKCS7Padding & kCCModeCBC, 
        vkey, 
        kCCKeySize3DES, 
        vinitVec, 
        vplainText, 
        plainTextBufferSize, 
        (void*)bufferPtr, 
        bufferPtrSize, 
        &movedBytes); 

NSData* result = [NSData dataWithBytes:(const void*)bufferPtr length:(NSUInteger)movedBytes]; 
NSString* str = [NSString base64StringFromData:result length:result.length]; 
NSLog(@"%@",str); 

return str; 
} 

我从Objective-C的代码,在.NET相比vplainTextvkeyvinitVec。他们是一样的。我得到的加密字符串是9SWzd+rlvu8=。我相信这是与填充有关。

这里就相当于.NET代码,他们正在使用:

protected string EncryptCreditCard(string creditCard) 
{ 
    try 
    { 
     string ENCRYPTION_KEY = ConfigurationManager.AppSettings["ENCRYPTION_KEY"].ToString(); 
     string ENCRYPTION_IV = ConfigurationManager.AppSettings["ENCRYPTION_IV"].ToString(); 

     SymmetricAlgorithm sa = SymmetricAlgorithm.Create("TripleDES"); 
     sa.Key = System.Convert.FromBase64String(ENCRYPTION_KEY); 
     sa.IV = System.Convert.FromBase64String(ENCRYPTION_IV); 
     sa.Padding = PaddingMode.Zeros; 

     byte[] inputByteArray = Encoding.ASCII.GetBytes(creditCard); 
     MemoryStream mS = new MemoryStream(); 

     ICryptoTransform trans = sa.CreateEncryptor(); 
     byte[] buf = new byte[2048]; 
     CryptoStream cs = new CryptoStream(mS, trans, CryptoStreamMode.Write); 
     cs.Write(inputByteArray, 0, inputByteArray.Length); 
     cs.FlushFinalBlock(); 

     return Convert.ToBase64String(mS.ToArray()); 
    } 
    catch 
    { 
     return ""; 
    } 
} 

我怎样才能在iOS正确的加密字符串?

回答

1

通过使用零填充。您的代码明确指出kCCOptionPKCS7Padding,这不是零填充。密文似乎是相同的,否则。

请注意,您最好在.NET代码中使用PaddingMode.PKCS7。它在奇数情况下添加了一些数据,即纯文本的大小已经是块大小的数倍,但它是标准化的,并且非压缩不再依赖于纯文本值。

+0

感谢您的回复猫头鹰。你将如何在iOS代码上应用零填充。我尝试在CCCrypt方法中将'0'作为参数传递给kCCOptionPKCS7Padding。它似乎不工作。 –

+0

您可能必须自己编程 - 零填充不是标准化的。零填充只是将零字节添加到明文,直到明文是块大小的倍数。在你的情况下,它不会垫,因为事实已经如此。请注意,零填充不应用于无法确定长度的二进制数据(因为二进制数据可能以字节设置为0结尾) –

+0

显然,最好在.NET中切换到“PaddingMode.PKCS7”。兼容的代码,以防万一你想知道。你要求做相反的事情,但建议使用PKCS#7填充。 –

0

问题出在用于加密的“密钥”。 iOS使用24Byte键,而Adnroid和.NET使用16Byte键。

已发布针对同一问题的详细解决方案,该问题描述了密钥生成。 Solution for different encryption value generated in iOS

+0

这不是iOS vs Adnroid问题,它是3DES键的两种不同方案。 3DES使用三个8字节密钥串行加密(3字节中只有56位用作密钥材料)。 “全”3DES是24字节,通常采用ede方案(使用第一个密钥进行加密,使用第二个密钥对输出进行解密,并使用第三个密钥对输出进行加密),但也有偶尔使用的其他序列。对于某些向后兼容系统(银行业务是主要的),有一个版本使用两个8字节密钥,一个使用两次。这就是Android在这里所做的。 – zaph

+0

@Zaph我提到的问题是使用的密钥。 Android或iOS没有问题。也感谢提及银行业,我不知道这一点。 –