通过两个 Web 域传输私钥的最佳解决方案

Posted

技术标签:

【中文标题】通过两个 Web 域传输私钥的最佳解决方案【英文标题】:Best solution to transfer private key over two web domain 【发布时间】:2020-05-12 19:05:45 【问题描述】:

将私钥传递到一个网站到另一个网站的最佳方式是什么。网站 A 将有一个带有加密 URL 的链接。单击链接后,它将转到需要解密加密文本的网站 B。加密是通过 RSA 完成的。 我可以看到两种方法可以在这里。 创建一次性私钥并与解密域共享。这里不需要在每个请求中都传递密钥。 另一个是每个请求都有两个创建密钥。在这种情况下,如何将密钥安全地传递给其他域。 哪种方法是最好的,或者我应该在安全方面做些什么。 或任何其他最佳解决方案。

【问题讨论】:

可能适合security.stackexchange.com 您使用什么协议来传输私钥?您能否使用简单的 https 隧道来传递敏感信息,而无需您的网站对其进行显式加密和解密? 我个人没有遇到任何需要通过网络传输私钥的用例。我怀疑你有其他选择。您是否知道公钥加密是专门设计的,因此私钥不需要通过网络传输?如果您描述您要解决的整个问题,而不是将其描述为“我需要通过网络传输私钥”,您可能会得到更好的答案。如果我正在审查通过网络发送私钥的架构,那对我来说将是一个很大的危险信号。 【参考方案1】:

您可以使用公钥加密技术将数据(在您的情况下为私钥)从一侧安全地发送到另一侧。虽然双方都可以访问公钥,但只有一方可以访问私钥。公钥用于加密数据,而私钥用于解密数据。可以通过这种方式加密的数据大小是有限的(通常只有 128-256 字节)。因此,通常这种技术用于加密/解密另一个加密/解密实际数据的加密密钥(AES ...)。

class Program

    static void Main(string[] args)
    
        // your data you want to securely send from B to A without revealing the content
        byte[] data = new byte[]  1, 2, 3, 4, 5, 6 ;

        // side A
        System.Security.Cryptography.RSACryptoServiceProvider full_rsa = new System.Security.Cryptography.RSACryptoServiceProvider(1024);

        byte[] publickey = full_rsa.ExportCspBlob(false);

        // send the public key to B
        // send(publickey)...

        // side B
        //send encrypted data back to side A
        byte[] encrypteddata = EncryptData(publickey, data); 

        // side A
        // decrypt the data encryped by side B
        byte[] decrypteddata = DecryptData(full_rsa, encrypteddata); 

        // decrypteddata = 1,2,3,4,5,6
    

    public static byte[] DecryptData(System.Security.Cryptography.RSACryptoServiceProvider full_rsa, byte[] data)
    
        System.IO.BinaryReader br = new System.IO.BinaryReader(new System.IO.MemoryStream(data));
        int encryptedkeylength = br.ReadInt32();
        int aeskeylength = br.ReadInt32();
        int aesivlength = br.ReadInt32();
        byte[] encryptedaeskey = br.ReadBytes(encryptedkeylength);
        byte[] encrypteddata = br.ReadBytes( (int)(data.Length - br.BaseStream.Position));
        br.Close();

        byte[] decryptedkey = full_rsa.Decrypt(encryptedaeskey, false);

        br = new System.IO.BinaryReader(new System.IO.MemoryStream(decryptedkey));
        using (System.Security.Cryptography.Aes myAes = System.Security.Cryptography.Aes.Create())
        
            byte[] aeskey = br.ReadBytes(aeskeylength);
            byte[] aesiv = br.ReadBytes(aesivlength);
            System.Security.Cryptography.ICryptoTransform decryptor = myAes.CreateDecryptor(aeskey, aesiv);

            using (System.IO.MemoryStream msDecrypt = new System.IO.MemoryStream())
            
                using (System.Security.Cryptography.CryptoStream csEncrypt = new System.Security.Cryptography.CryptoStream(msDecrypt, decryptor, System.Security.Cryptography.CryptoStreamMode.Write))
                
                    using (System.IO.BinaryWriter bw = new System.IO.BinaryWriter(csEncrypt))
                    
                        bw.Write(encrypteddata);
                    
                    return msDecrypt.ToArray();
                
            
        
    

    public static byte[] EncryptData(byte[] publickey, byte[] data)
    
        using (System.Security.Cryptography.Aes myAes = System.Security.Cryptography.Aes.Create())
        
            System.Security.Cryptography.ICryptoTransform encryptor = myAes.CreateEncryptor(myAes.Key, myAes.IV);

            using (System.IO.MemoryStream msEncrypt = new System.IO.MemoryStream())
            
                using (System.Security.Cryptography.CryptoStream csEncrypt = new System.Security.Cryptography.CryptoStream(msEncrypt, encryptor, System.Security.Cryptography.CryptoStreamMode.Write))
                
                    System.IO.MemoryStream headerms = new System.IO.MemoryStream();
                    System.IO.BinaryWriter headerbw = new System.IO.BinaryWriter(headerms);

                    using (System.IO.BinaryWriter bw = new System.IO.BinaryWriter(csEncrypt))
                    
                        System.Security.Cryptography.RSACryptoServiceProvider public_key = new System.Security.Cryptography.RSACryptoServiceProvider(1024);
                        public_key.ImportCspBlob(publickey);

                        byte[] encryptedkey = public_key.Encrypt(Combine(myAes.Key, myAes.IV), false);
                        headerbw.Write(encryptedkey.Length);
                        headerbw.Write(myAes.Key.Length);
                        headerbw.Write(myAes.IV.Length);
                        headerbw.Write(encryptedkey);
                        headerbw.Flush();
                        bw.Write(data);
                                                

                    byte[] result = Combine(headerms.ToArray(), msEncrypt.ToArray());
                    headerbw.Close();
                    return result;
                
            
        
    

    static byte[] Combine(byte[] first, byte[] second)
    
        byte[] ret = new byte[first.Length + second.Length];
        Buffer.BlockCopy(first, 0, ret, 0, first.Length);
        Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
        return ret;
    

【讨论】:

以上是关于通过两个 Web 域传输私钥的最佳解决方案的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 powershell 授予用户对证书私钥的权限?

JWT:带有公钥/私钥的 jwtk/jjwt

RSA公钥私钥的作用

关于RSA中公钥和私钥的具体使用情况区分

开放 ssh 私钥的确切格式

请问SSL加密的公钥和私钥区别