与Inferno的ECIES:使用ECDSA签名

时间:2016-12-08 18:39:49

标签: c# ecdsa ecies

我正在尝试使用Inferno签署使用ECIES加密的文本文件。加密和密钥交换部分运行良好,但我留下了一些关于ECDSA的问题。

1-我猜ECDSA签名必须存储在已发送的文件中,以便接收方可以使用它来验证数据的完整性,对吗?

2-我多次读过应该对散列数据进行签名,但是使用ECIES发送的数据是加密的,而不是哈希,否则接收方如何检索它?

3-以下代码示例中的哪个位置应该进行签名?当前尝试不起作用,因为虽然签名在解密时被接受,但返回空字符串(而不是解密文本)。

    internal static void EncryptText(string text, Keyring k, string file, bool forSender)
    {
        // never mind the Keyring class, it has no methods and only exposes
        // a few properties to store the session keys conveniently

        SharedEphemeralBundle ephemeralBundle;
        if (forSender) ephemeralBundle = k.SenderDHM.GetSharedEphemeralDhmSecret();
        else ephemeralBundle = k.ReceiverDHM.GetSharedEphemeralDhmSecret();

        var ephemeralPublic = ephemeralBundle.EphemeralDhmPublicKeyBlob;
        var ephemeralSymmetric = ephemeralBundle.SharedSecret;
        var textBytes = Utils.SafeUTF8.GetBytes(text);

        byte[] signature;            
        using (var ecdsa = new ECDsaCng(k.SenderDSA) { HashAlgorithm = CngAlgorithm.Sha384 })
            signature = ecdsa.SignData(textBytes);

        using (FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write))
        {
            fs.Write(signature, 0, signature.Length);
            fs.Write(ephemeralPublic, 0, ephemeralPublic.Length);

            EtM_EncryptTransform etm = new EtM_EncryptTransform(ephemeralSymmetric);
            using (CryptoStream cs = new CryptoStream(fs, etm, CryptoStreamMode.Write))                
                cs.Write(textBytes, 0, textBytes.Length);                                   
        }            
    }

    internal static string DecryptText(string file, Keyring k)
    {
        string decrypted = null;            
        var ephemeralPublic = new byte[104];
        var signature = new byte[96];            

        using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
        {
            fs.Read(signature, 0, 96);
            fs.Read(ephemeralPublic, 0, 104);

            var ephemeralSymmetric = k.SenderDHM.GetSharedDhmSecret(ephemeralPublic.ToPublicKeyFromBlob());
            EtM_DecryptTransform etm = new EtM_DecryptTransform(ephemeralSymmetric);
            using (CryptoStream cs = new CryptoStream(fs, etm, CryptoStreamMode.Read))
            {
                byte[] decrypt = new byte[fs.Length - 200];
                cs.Read(decrypt, 0, decrypt.Length);
                using (var ecdsa = new ECDsaCng(k.SenderDSA))
                {
                    // signature is accepted but returns an empty string!?
                    if (ecdsa.VerifyData(decrypt, signature))
                        decrypted = Utils.SafeUTF8.GetString(decrypt);                        
                }                        
            }                                                                                       
        }
        return decrypted;
    }

1 个答案:

答案 0 :(得分:0)

好吧没关系,经过仔细检查看起来在我的情景中,幸运的是我可以单独使用HMAC:

    private static bool Authenticate(string file, byte[] key, bool masterKey = false)
    {
        int position = 104;
        if (masterKey) position = 48; 
        using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
        using (var etm = new EtM_DecryptTransform(key, authenticateOnly: true))
        {
            fs.Position = position;
            using (var cs = new CryptoStream(fs, etm, CryptoStreamMode.Read))
                cs.CopyTo(Stream.Null);

            if (!etm.IsComplete) throw new Exception("Some blocks were not authenticated");
        }
        return true;
    }        

    internal static void EncryptText(string text, Keyring k, string file, bool forSender)
    {
        SharedEphemeralBundle ephemeralBundle;
        if (forSender) ephemeralBundle = k.SenderDHM.GetSharedEphemeralDhmSecret();
        else ephemeralBundle = k.ReceiverDHM.GetSharedEphemeralDhmSecret();

        var ephemeralPublic = ephemeralBundle.EphemeralDhmPublicKeyBlob;
        var ephemeralSymmetric = ephemeralBundle.SharedSecret;
        var textBytes = text.ToBytes();                       

        using (var fs = new FileStream(file, FileMode.Create, FileAccess.Write))
        {                
            fs.Write(ephemeralPublic, 0, ephemeralPublic.Length);
            using (var etm = new EtM_EncryptTransform(ephemeralSymmetric))
            using (var cs = new CryptoStream(fs, etm, CryptoStreamMode.Write))
                cs.Write(textBytes, 0, textBytes.Length);                                                                                       
        }            
    }

    internal static string DecryptText(string file, Keyring k)
    {
        string decrypted = null;            
        var ephemeralPublic = new byte[104];

        using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
        {                
            fs.Read(ephemeralPublic, 0, 104);
            var ephemeralSymmetric = k.SenderDHM.GetSharedDhmSecret(ephemeralPublic.ToPublicKeyFromBlob());
            if (Authenticate(file, ephemeralSymmetric))
            {
                using (var etm = new EtM_DecryptTransform(ephemeralSymmetric))
                using (var cs = new CryptoStream(fs, etm, CryptoStreamMode.Read))
                {
                    var decrypt = new byte[fs.Length - 104];
                    cs.Read(decrypt, 0, decrypt.Length);
                    decrypted = decrypt.FromBytes();
                }
            }                                                                                                          
        }
        return decrypted;
    }