加密API< - > .NET RSA互操作性

时间:2009-03-29 01:56:00

标签: c# rsa cryptoapi

我有一个非托管应用程序,它使用Crypto API生成RC4加密密钥。此非托管应用程序使用此RC4密钥加密某些数据。还有一个客户端非托管应用程序使用此RC4密钥来解密信息。

但是,对于此客户端应用,我们发送会话密钥 - > RC4密钥使用在客户端生成的RSA公钥(SIMPLEBLOB)加密。加密会话密钥的生成过去是使用非托管代码完成的,但现在必须转换为C#,因为需要在部分信任的情况下从Web应用程序运行此代码。

使用

生成密钥
CryptGenKey(hProv, CALG_RC4, KEY_LENGTH | CRYPT_EXPORTABLE, &hKey);

使用

将其导出到文件系统中
CryptExportKey(hKey, 0, OPAQUEKEYBLOB, 0, lpBuffer, &nSize);

(注意我可以使用这篇文章导出纯文本密钥 http://www.codeproject.com/KB/security/plaintextsessionkey.aspx

使用

创建客户端公钥
CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKeyPair);

使用

导出客户端公钥
CryptExportKey(hKeyPair, 0, PUBLICKEYBLOB, 0, lpData, &nSize);

使用

在服务器端创建会话密钥
  1. 使用

    导入客户端公钥

    CryptImportKey(hProv,lpData,nSize,NULL,0,& hPublicKey

  2. 通过使用客户端公钥加密RC4生成会话密钥以生成SIMPLEBLOB格式

    CryptExportKey(hKey,hPublicKey,SIMPLEBLOB,0,lpData,& nSize);

  3. 现在我的要求是在托管版本中执行上述步骤(步骤1和2),这就是我正在做的事情:

    //读取使用代码项目文章提取的纯文本密钥数据     byte [] keyMaterial = File.ReadAllBytes(@“C:\ keyMaterial.txt”);

    //导入客户端公钥

    CspParameters cspParams = new CspParameters();
                cspParams.KeyContainerName = "Container Name";
                cspParams.KeyNumber = (int)KeyNumber.Exchange;
                cspParams.ProviderType = 1;
                cspParams.ProviderName = "Microsoft Enhanced Cryptographic Provider v1.0";
                cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
    
                RSACryptoServiceProvider rsaClient = new RSACryptoServiceProvider(cspParams);   
                rsaClient.ImportCspBlob(File.ReadAllBytes(@"C:\client.key"));
    
    //Generate a SIMPLEBLOB session key
    byte[] session = GetRC4SessionBlobFromKey(keyMaterial, rsaClient);
    
    
    
    //Encrypt a key using public key and write it in a SIMPLEBLOB format
    public byte[] GetRC4SessionBlobFromKey(byte[] keyData, RSACryptoServiceProvider publicKey)
            {  
                using(MemoryStream ms = new MemoryStream())  
                using(BinaryWriter w = new BinaryWriter(ms))
                {   
                    w.Write((byte) 0x01); // SIMPLEBLOB    
                    w.Write((byte) 0x02); // Version 2    
                    w.Write((byte) 0x00); // Reserved    
                    w.Write((byte) 0x00); // Reserved    
                    w.Write(0x00006801);  // ALG_ID = RC4 for the encrypted key.
                    w.Write(0x0000a400);  // CALG_RSA_KEYX    
    
                    w.Write(publicKey.Encrypt(keyData, false));
                    w.Flush();
    
                    return ms.ToArray();  
                }
            }
    

    这会生成与非托管版本相同大小的数据,但它不会像非托管版本的第1步和第2步那样生成正确的SIMPLEBLOB会话密钥。我在这段代码中做错了什么?

1 个答案:

答案 0 :(得分:1)

我是新手,但我只是在MSDN文档中阅读以下内容:

与Microsoft Cryptographic API(CAPI)的互操作

与非托管CAPI中的RSA实现不同,RSACryptoServiceProvider类在加密后和解密之前反转加密字节数组的顺序。默认情况下,CAPAC CryptDecrypt函数无法解密由RSACryptoServiceProvider类加密的数据,并且RSACryptoServiceProvider类无法解密由CAPI CryptEncrypt方法加密的数据。

如果在API之间进行互操作时没有补偿反向排序,则RSACryptoServiceProvider类会抛出CryptographicException。

这可能是问题吗?

相关问题