遇到问题解密在C#的东西对iPhone使用RSA加密 [英] Having trouble decrypting in C# something encrypted on iPhone using RSA

查看:251
本文介绍了遇到问题解密在C#的东西对iPhone使用RSA加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对这个迄今花了两天时间,并通过在我手上每个源梳理,所以这是最后的手段。

I've spent two days on this so far and combed through every source at my disposal, so this is the last resort.

我有一个X509证书,其公共密钥我已经(仅在这一点上仿真器)存储在iPhone的钥匙串。在ASP.NET的一面,我已经得到的证书存储用私钥证书。当我加密在iPhone上的字符串和解密在服务器上,我收到了 CryptographicException 坏数据。我试图在的 Array.Reverse 建议http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider的.aspx相对=nofollow> 的RSACryptoServiceProvider 一个远射页,但它并没有帮助。

I have an X509 certificate whose public key I have stored in the iPhone's keychain (simulator only at this point). On the ASP.NET side, I've got the certificate in the cert store with a private key. When I encrypt a string on the iPhone and decrypt it on the server, I get a CryptographicException "Bad data." I tried the Array.Reverse suggested in the RSACryptoServiceProvider page on a longshot, but it did not help.

我比较两侧基部64的字符串和它们相等。我已经比较解码后的原始字节数组,他们也都是平等的。如果我使用加密的公钥服务器上,字节数组是从iPhone的版本不同,容易解密使用私钥。原始明文字符串为115个字符所以这是我的2048位密钥的256字节的限制之内。

I have compared the base-64 strings on both sides and they're equal. I've compared the raw byte arrays after decoding and they too are equal. If I encrypt on the server using the public key, the byte array is different from the iPhone's version and readily decrypts using the private key. The raw plaintext string is 115 characters so it's within the 256-byte limitation of my 2048-bit key.

下面是iPhone的加密方法(从<一个几乎逐字HREF =htt​​p://developer.apple.com/iphone/library/samplecode/CryptoExercise/listing15.html相对=nofollow> CryptoExercise示例应用程序的 wrapSymmetricKey 法):

Here's the iPhone encryption method (pretty much verbatim from the CryptoExercise sample app's wrapSymmetricKey method):

+ (NSData *)encrypt:(NSString *)plainText usingKey:(SecKeyRef)key error:(NSError **)err
{
    size_t cipherBufferSize = SecKeyGetBlockSize(key);
    uint8_t *cipherBuffer = NULL;
    cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
    memset((void *)cipherBuffer, 0x0, cipherBufferSize);
    NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];
    OSStatus status = SecKeyEncrypt(key, kSecPaddingNone,
                                (const uint8_t *)[plainTextBytes bytes], 
                                [plainTextBytes length], cipherBuffer, 
                                &cipherBufferSize);
    if (status == noErr)
    {
        NSData *encryptedBytes = [[[NSData alloc]
                    initWithBytes:(const void *)cipherBuffer 
                    length:cipherBufferSize] autorelease];
        if (cipherBuffer)
        {
            free(cipherBuffer);
        }
        NSLog(@"Encrypted text (%d bytes): %@",
                    [encryptedBytes length], [encryptedBytes description]);
        return encryptedBytes;
    }
    else
    {
        *err = [NSError errorWithDomain:@"errorDomain" code:status userInfo:nil];
        NSLog(@"encrypt:usingKey: Error: %d", status);
        return nil;
    }
}

和这里的服务器端的C#解密方法:

And here's the server-side C# decryption method:

private string Decrypt(string cipherText)
{
    if (clientCert == null)
    {
        // Get certificate
        var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        foreach (var certificate in store.Certificates)
        {
            if (certificate.GetNameInfo(X509NameType.SimpleName, false) == CERT)
            {
                clientCert = certificate;
                break;
            }
        }
    }

    using (var rsa = (RSACryptoServiceProvider)clientCert.PrivateKey)
    {
        try
        {
            var encryptedBytes = Convert.FromBase64String(cipherText);
            var decryptedBytes = rsa.Decrypt(encryptedBytes, false);
            var plaintext = Encoding.UTF8.GetString(decryptedBytes);
            return plaintext;
        }
        catch (CryptographicException e)
        {
            throw(new ApplicationException("Unable to decrypt payload.", e));
        }
    }
}



我的怀疑是,有平台之间的一些编码问题。 <罢>我知道,一个是big-endian和另一种是小端,但我不知道足够说哪个是哪个或如何克服差异。的Mac OS X,Windows和iPhone 。都是小尾数所以这不是问题。

My suspicion was that there was some encoding problems between the platforms. I know that one is big-endian and the other is little-endian but I don't know enough to say which is which or how to overcome the difference. Mac OS X, Windows, and the iPhone are all little-endian so that's not the problem.

<击>新理论:如果你的OAEP填充布尔设置为false,则默认为PKCS#1 1.5填充。 SecKey 只有 SecPadding PKCS1 ,<$ C的定义$ C> PKCS1MD2 , PKCS1MD5 PKCS1SHA1 。也许微软的PKCS#1 1.5!=苹果PKCS1等填充是影响了加密的二进制输出。我试着用 kSecPaddingPKCS1 fOAEP 设置为和它仍然没有奏效。显然, kSecPaddingPKCS1 是的相当于以PKCS#1 1.5。返回的理论和hellip绘图板;

New theory: if you set the OAEP padding Boolean to false, it defaults to PKCS#1 1.5 padding. SecKey only has SecPadding definitions of PKCS1, PKCS1MD2, PKCS1MD5, and PKCS1SHA1. Perhaps Microsoft's PKCS#1 1.5 != Apple's PKCS1 and so the padding is affecting the binary output of the encryption. I tried using kSecPaddingPKCS1 with the fOAEP set to falseand it still didn't work. Apparently, kSecPaddingPKCS1 is equivalent to PKCS#1 1.5. Back to the drawing board on theories…

其他新尝试的理论:


  1. 证书在iPhone(.cer文件)是不完全一样的PKCS#12束服务器(.pfx文件),因此它不可能努力。在不同的证书存储和服务器加密的字符串装.CER文件roundtripped就好了;

  2. 转换到基于64位和张贴到服务器的行为导致怪异之处是不存在于同一个类往返,所以我第一次尝试了一些URL编码/解码,然后贴原料从iPhone,二元验证,这是平等的,并得到了同样的错误数据;

  3. 我原来的字符串为125个字节,所以我想这可能是UTF-8(长镜头)被截断,所以我没有结果裁剪下来到一个44字节的字符串;

  4. 回头一看在System.Cryptography库以确保我使用适当的类发现'RSAPKCS1KeyExchangeDeformatter`,成为了新的前景心花怒放,和沮丧时它的表现究竟一样。

  1. Certificate on iPhone (.cer file) is not exactly the same as the PKCS#12 bundle on the server (.pfx file) and so it could never work. Installed .cer file in different cert store and server-encrypted string roundtripped just fine;
  2. Conversion to base-64 and act of POSTing to server resulted in oddness that wasn't present in same class roundtrip so I first tried some URLEncoding/Decoding and then posted raw binary from iPhone, verified that it was equal, and got same bad data;
  3. My original string was 125 bytes so I thought it might be truncating in UTF-8 (long shot) so I cropped it down to a 44-byte string with no result;
  4. Looked back over the System.Cryptography library to make sure I was using an appropriate class and discovered `RSAPKCS1KeyExchangeDeformatter`, became elated at new prospects, and dejected when it behaved exactly the same.

成功!

原来,我在我的iPhone模拟器被弄脏水钥匙扣一些克鲁夫特,可以这么说。我删除了钥匙串DB在〜/库/应用程序支持/ iPhone模拟器/用户/图书馆/钥匙扣/钥匙扣-2- debug.db 以使其重新创建它工作得很好。感谢您所有的帮助。图这本来是简单的东西,但不明显。 (两件事情我了解到:1)从模拟器卸载应用程序不清除其钥匙扣条目和2)开始绝对新鲜定期)

It turned out that I had some cruft in my Keychain on the iPhone Simulator that was muddying the waters, so to speak. I deleted the Keychain DB at ~/Library/Application Support/iPhone Simulator/User/Library/Keychains/keychain-2-debug.db to cause it to be re-created and it worked fine. Thank you for all of your help. Figures it would have been something simple but non-obvious. (Two things I learned: 1) uninstalling the app from the simulator does not clear its Keychain entries and 2) start absolutely fresh periodically.)

注:通用路径钥匙串文件是依赖于iOS版本:
〜/库/应用程序支持/ iPhone模拟器/ [版本] /Library/Keychains/keychain-2-debug.db
例如,
〜 /库/应用程序支持/ iPhone模拟器/ 4.3 /图书馆/钥匙扣/钥匙扣-2- debug.db

NOTE: The generic path for the keychain file is dependent on the iOS version: ~/Library/Application Support/iPhone Simulator/[version]/Library/Keychains/keychain-2-debug.db e.g., ~/Library/Application Support/iPhone Simulator/4.3/Library/Keychains/keychain-2-debug.db

推荐答案

嗯.. 。第一步(如你所说,你所做的)是相同的消息与同时使用iPhone和C#实现相同的初始化向量加密。你应该得到相同的输出。你说你没有,所以出现了问题。

Well... the first step (as you say you have done) is to encrypt the same messages with the same initialization vectors using both the iPhone and the C# implementation. You should get the same output. You said you didn't, so there is a problem.

这指:


  • RSA的iPhone执行不正确。

  • RSA的.NET实现不正确。

  • 的关键文件是不同的(或所不同的解释)。

我建议前两个是不可能的,但他们是远程可能。

I would suggest the first two are unlikely, however they are remotely possible.

您状态:在不同的证书存储和服务器加密的字符串安装.CER文件roundtripped就好了......这并不能证明什么:所有这一切证明是给定一个特定的随机组数字可以加密/在一个平台上成功解密。你是不是低保两个平台都看到同一组随机数字。

You state: "Installed .cer file in different cert store and server-encrypted string roundtripped just fine"... this doesn't prove anything: all this proves is that given a particular random set of numbers you can encrypt/decrypt successfully on one platform. You are not guaranteeing that both platforms are seeing the same set of random numbers.

因此​​,我建议你把它降低到最低水平可能在这里。检查的两个平台上的加密直接(字节数组)的输入和输出。如果具有完全相同(二进制)输入你没有得到相同的输出,那么你有一个平台问题。我觉得这是不可能的,所以我猜你会发现,室间隔正在不同的解释。

So I suggest you take it down to the lowest level possible here. Inspect the direct (byte array) inputs and outputs of the encryption on both platforms. If with the exact same (binary) inputs you don't get the same output, then you have a platform problem. I think this is unlikely, so I'm guessing you will find that the IVs are being interpreted differently.

这篇关于遇到问题解密在C#的东西对iPhone使用RSA加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆