0

我正在尝试使用 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;
    }
4

1 回答 1

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;
    }
于 2016-12-09T05:39:14.847 回答