我有一个 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();
}
我也有实现上述所有功能的代码,但我认为它们对解决我的问题没有必要。我希望这些信息和代码足以让您能够帮助我。 感谢我能得到的任何帮助!