2

我正在尝试在 iOS 上使用 3DES 和 CBC 模式加密来加密 NSString。

ASP.NET 上也使用了相同的加密方法,并且它们获得的加密字符串可与 Web 服务一起使用。woodcraft554从 .NET 代码中获取的加密字符串是: 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;
}

我已经比较了vplainText,vkey以及vinitVec从 Objective-C 代码到 .NET 中的代码。他们是一样的。我得到的加密字符串是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 中获得正确的加密字符串?

4

2 回答 2

1

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

请注意,最好PaddingMode.PKCS7在 .NET 代码中使用。它会在奇怪的情况下添加一些数据,即纯文本的大小已经是块大小的数倍,但它是标准化的,并且取消填充不再取决于纯文本值。

于 2012-10-01T07:43:58.207 回答
0

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

已针对同一问题发布了详细的解决方案,其中描述了密钥生成。iOS产生不同加密值的解决方案

于 2014-10-20T05:19:48.797 回答