代码之家  ›  专栏  ›  技术社区  ›  Jens

NET中最小消息大小的公钥加密

  •  11
  • Jens  · 技术社区  · 14 年前

    我想使用公钥密码系统将非常少的数据(准确地说是15字节)加密成一个尽可能短的消息(最好不要超过16字节)。

    为了使事情变得更困难,我只能使用.NETFramework库,即没有第三方。

    我在维基百科上读过一些关于椭圆曲线密码术的文章,其中的文字似乎表明,那里的密钥大小通常比RSA密钥短得多。

    ECDiffieHellmanCng 类是否用于对消息进行反加密?它的特点似乎与RSA或对称密码不同。

    2 回复  |  直到 10 年前
        1
  •  11
  •   Rasmus Faber    14 年前

    您可以使用ECDiffieHellman加密消息。您有两个选项:静态ECDH和静态临时ECDH:

    对于静态ECDH,接收方需要知道发送方的公钥(这可能是应用程序中的一个选项,也可能不是)。您还应该有一些对此消息唯一的数据(它可能是从协议或数据库行中的其他位置获得的序列号,或者其他任何数据,也可能是nonce)。然后使用ECDH生成一个密钥并用它加密数据。这将为您提供所需的16字节的加密数据长度,但这并不是完全不对称的:加密程序还能够解密消息(同样:这在您的应用程序中可能是问题,也可能不是问题)。

    静态临时密钥有点不同:这里加密程序生成一个临时(临时)EC密钥对。然后他使用这个密钥对和接收者的公钥来生成一个可以用来加密数据的密钥。最后,他将临时密钥对的公钥与加密数据一起发送给接收器。这可能更适合您的应用程序,但使用ECDH-256和AES,完整的加密数据现在将是2*32+16=80字节(正如GregS所指出的,您只需发送公钥的x坐标就可以节省32字节,但我不相信.NET公开了重新计算y坐标的功能)。

    下面是一个小类,它将执行静态ECDH:

    public static class StaticStaticDiffieHellman
    {
      private static Aes DeriveKeyAndIv(ECDiffieHellmanCng privateKey, ECDiffieHellmanPublicKey publicKey, byte[] nonce)
      {
        privateKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
        privateKey.HashAlgorithm = CngAlgorithm.Sha256;
        privateKey.SecretAppend = nonce;
        byte[] keyAndIv = privateKey.DeriveKeyMaterial(publicKey);
        byte[] key = new byte[16];
        Array.Copy(keyAndIv, 0, key, 0, 16);
        byte[] iv = new byte[16];
        Array.Copy(keyAndIv, 16, iv, 0, 16);
    
        Aes aes = new AesManaged();
        aes.Key = key;
        aes.IV = iv;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
    
        return aes;
      }
    
      public static byte[] Encrypt(ECDiffieHellmanCng privateKey, ECDiffieHellmanPublicKey publicKey, byte[] nonce, byte[] data){
        Aes aes = DeriveKeyAndIv(privateKey, publicKey, nonce);
        return aes.CreateEncryptor().TransformFinalBlock(data, 0, data.Length);
      }
    
      public static byte[] Decrypt(ECDiffieHellmanCng privateKey, ECDiffieHellmanPublicKey publicKey, byte[] nonce, byte[] encryptedData){
        Aes aes = DeriveKeyAndIv(privateKey, publicKey, nonce);
        return aes.CreateDecryptor().TransformFinalBlock(encryptedData,0, encryptedData.Length);
      }
    }
    
    // Usage:
    
    ECDiffieHellmanCng key1 = new ECDiffieHellmanCng();    
    ECDiffieHellmanCng key2 = new ECDiffieHellmanCng();
    
    byte[] data = Encoding.UTF8.GetBytes("TestTestTestTes");
    byte[] nonce = Encoding.UTF8.GetBytes("whatever");
    
    byte[] encryptedData = StaticStaticDiffieHellman.Encrypt(key1, key2.PublicKey, nonce, data);
    
    Console.WriteLine(encryptedData.Length); // 16
    
    byte[] decryptedData = StaticStaticDiffieHellman.Decrypt(key2, key1.PublicKey, nonce, encryptedData);
    
    Console.WriteLine(Encoding.UTF8.GetString(decryptedData));
    
        2
  •  0
  •   Sani Huttunen    14 年前

    ECDiffieHellmanCNG是原始Diffie-Hellman密钥交换协议的派生。
    它不用于加密消息,而是在两端计算相同的秘密值。

    Here 是关于电子商务及其目的的一些信息。