如何使用唯一生成的密钥使用 RSA 在 C# 中加密和解密数据?

问题描述 投票:0回答:0

我有一个 Bruce Schneier 的数字现金实施方案。我用 C# 编写这个程序,使用 Visual Studio 2022,并使用 Windows 窗体应用程序。为了正确地做到这一点,我必须使用 RSA 盲加密来隐藏数据,用私钥加密它,然后我将它发送到“银行”来签署数据,然后我将解密和取消数据。 我有用于加密(公共和私有)、解密(公共和私有)、致盲、揭盲、签名和生成密钥对的代码。

我不确定我的问题到底出在哪里,但是我的私钥中的D值有时会生成负数,这会导致错误。此外,当 D 值为正时,加密值为 0,则解密值为 0。

更糟糕的是,我的盲函数和非盲函数也有问题。当对我的盲数据进行揭盲时,数据的大小增加了一倍(从大约 30 位数增加到大约 60 位数)。造成这种情况的原因可能是我的 ModInverse 函数中的一个错误,因为我使用的 BigInteger 库不包含 ModInverse 函数,所以我对盲数据进行了揭盲。我做了一个例外,我认为问题是盲人是不可逆的(可能是 ModInverse 函数错误)。

关于我的代码。 为了生成密钥,我做了这个功能:

            // Generate RSA key pair
            using RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048);

            // Export public key to file
            string publicKeyFile = "publickey.xml";
            File.WriteAllText(publicKeyFile, rsa.ToXmlString(false));

            // Export private key to file
            string privateKeyFile = "privatekey.xml";
            File.WriteAllText(privateKeyFile, rsa.ToXmlString(true));

            // Export public key to separate directory for the bank and merchant
            string bankDirectory = "C:\\Users\\bentu\\OneDrive\\Documents\\GitHub\\DigitalCash\\DigitalCash\\Bank\\bin\\Debug\\net7.0-windows\\";
            string merchantDirectory = "C:\\Users\\bentu\\OneDrive\\Documents\\GitHub\\DigitalCash\\DigitalCash\\Merchant\\bin\\Debug\\net7.0-windows\\";

            File.WriteAllText(Path.Combine(bankDirectory, publicKeyFile), rsa.ToXmlString(false));
            File.WriteAllText(Path.Combine(bankDirectory, privateKeyFile), rsa.ToXmlString(true));
            File.WriteAllText(Path.Combine(merchantDirectory, publicKeyFile), rsa.ToXmlString(false));

加密、解密、盲化、解除盲化和ModInverse函数是这些:

// Encrypt data using private key
        public byte[] PrivateEncryption(byte[] data)
        {
            if (!IsPrivateKeyLoaded)  // is the private key has been loaded?
                throw new CryptographicException
                    ("Private Key must be loaded before using the Private Encryption method!");

            // Converting the byte array data into a BigInteger instance
            BigInteger bnData = new BigInteger(data);

            // (bnData ^ D) % Modulus - This Encrypt the data using the private Exponent: D
            BigInteger encData = BigInteger.ModPow(bnData, D, Modulus);
            return encData.ToByteArray();
        }

        // Encrypt data using public key
        public byte[] PublicEncryption(byte[] data)
        {
            if (!IsPublicKeyLoaded)  // is the public key has been loaded?
                throw new CryptographicException
                    ("Public Key must be loaded before using the Public Encryption method!");

            // Converting the byte array data into a BigInteger instance
            BigInteger bnData = new BigInteger(data);

            // (bnData ^ Exponent) % Modulus - This Encrypt the data using the public Exponent
            BigInteger encData = BigInteger.ModPow(bnData, Exponent, Modulus);
     
            return encData.ToByteArray();
            
        }


        public void createBlindFactor()
        {
            Boolean done = false;  //finding a blind factor
            Random rnd = new Random();//finding a blind factor
            blind = rnd.Next(1000000, 2100000000);//finding a blind factor
            while (done != true)//finding a blind factor
            {
                if (BigInteger.GreatestCommonDivisor(Modulus, blind) == 1) done = true;//finding a blind factor
                else blind = rnd.Next(1000000, 2100000000);//finding a blind factor

            }

            return;
        }


        public string retrieveBlindFactor()
        {
            return blind.ToString();

        }

        public void setBlindFactor(BigInteger tempBlind)
        {
            // Converting the byte array data into a BigInteger instance
            //BigInteger bnBlind = new BigInteger(tempBlind);
            //blind = bnBlind;
            blind = tempBlind;

        }

        public string PublicBlindEncryption(byte[] data)
        {
            
            // Converting the byte array data into a BigInteger instance
            BigInteger bnData = new BigInteger(data);
            

            enBlind = BigInteger.ModPow(blind, Exponent, Modulus); //encrypting the blind factor
            BigInteger encBlindData = enBlind * bnData; //blinding the message with encrypted blindfactor

           //return encBlindData.getBytes();
            return encBlindData.ToString();
           
        }

        // Decrypt data using private key (for data encrypted with public key)
        public byte[] PrivateDecryption(byte[] encryptedData)
        {
            if (!IsPrivateKeyLoaded)  // is the private key has been loaded?
                throw new CryptographicException
                    ("Private Key must be loaded before using the Private Decryption method!");

            // Converting the encrypted data byte array data into a BigInteger instance
            BigInteger encData = new BigInteger(encryptedData);

            // (encData ^ D) % Modulus - This Decrypt the data using the private Exponent: D
            BigInteger bnData = BigInteger.ModPow(encData, D, Modulus);
            BigInteger inverseb = BigInteger.ModPow(blind, -1, Modulus);
            return bnData.ToByteArray();
        }

        // Decrypt data using public key (for data encrypted with private key)
        public byte[] PublicDecryption(byte[] encryptedData)
        {
            if (!IsPublicKeyLoaded)  // is the public key has been loaded?
                throw new CryptographicException
                    ("Public Key must be loaded before using the Public Deccryption method!");

            // Converting the encrypted data byte array data into a BigInteger instance
            BigInteger encData = new BigInteger(encryptedData);

            // (encData ^ Exponent) % Modulus - This Decrypt the data using the public Exponent
            BigInteger bnData = BigInteger.ModPow(encData, Exponent, Modulus);
            return bnData.ToByteArray();
        }

        public static BigInteger ModInverse(BigInteger a, BigInteger n)
        {
            BigInteger t = 0, newt = 1;
            BigInteger r = n, newr = a;

            while (newr != 0)
            {
                BigInteger quotient = r / newr;

                (t, newt) = (newt, t - quotient * newt);
                (r, newr) = (newr, r - quotient * newr);
            }

            if (r > 1)
            {
                throw new Exception("a is not invertible");
            }

            if (t < 0)
            {
                t += n;
            }

            return t;
        }


        public string Unblind(BigInteger data)
        //public byte[] unblind(byte[] data)
        {
            
            // Converting the encrypted data byte array data into a BigInteger instance
            //BigInteger bnData = new BigInteger(data);
            BigInteger bnData = data;
            BigInteger unBlindedData;
            BigInteger invblind = ModInverse(blind, Modulus);   // Finding the inverse of blind factor
            unBlindedData = invblind * bnData;      // Unblinding the signed message
            //return unBlindedData.getBytes();
            return unBlindedData.ToString();
            
        }

我也有实现上述所有功能的代码,但我认为它们对解决我的问题没有必要。我希望这些信息和代码足以让您能够帮助我。 感谢我能得到的任何帮助!

c# cryptography rsa blind-signature
© www.soinside.com 2019 - 2024. All rights reserved.