【问题标题】:Crypto API <-> .NET RSA interoperability加密 API <-> .NET RSA 互操作性
【发布时间】:2009-03-29 01:55:59
【问题描述】:

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

但是,对于此客户端应用,我们发送的是会话密钥 -> 使用客户端生成的 RSA 公钥 (SIMPLEBLOB) 加密的 RC4 密钥。加密会话密钥的生成过去是使用非托管代码完成的,但现在必须将其转换为 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 生成 SIMPLEBOB 格式来生成的

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

现在我的要求是在托管版本中包含上述步骤(第 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 会话密钥。我在这段代码中做错了什么?

【问题讨论】:

    标签: c# rsa cryptoapi


    【解决方案1】:

    我是这里的新手,但我刚刚在 MSDN 文档中阅读了以下内容:

    与 Microsoft Cryptographic API (CAPI) 的互操作

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

    如果在 API 之间互操作时不补偿反向排序,RSACryptoServiceProvider 类将引发 CryptographicException。

    这可能是问题吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-02
      • 1970-01-01
      • 2011-05-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多