我有一个功能,产生BouncyCastle RSA密的成对钥匙。我需要密私人钥匙然后储存的经加密的私人和公共键成独立的SQL2008数据库的字段。

我使用的以下要得到密钥对:

private static AsymmetricCipherKeyPair createASymRandomCipher()
{
    RsaKeyPairGenerator r = new RsaKeyPairGenerator();
    r.Init(new KeyGenerationParameters(new SecureRandom(), 1024));
    AsymmetricCipherKeyPair keys = r.GenerateKeyPair();
    return keys; 
}

这是返回的钥匙好的,但我不知道该如何然后我就可以进行加密的私人钥匙并随后将其存储在数据库。

这是我目前使用的加密数据(不正确?):

public static byte[] encBytes2(AsymmetricKeyParameter keyParam, byte[] Key, byte[] IV)
{
    MemoryStream ms = new MemoryStream();
    Rijndael rjdAlg = Rijndael.Create();
    rjdAlg.Key = Key;
    rjdAlg.IV = IV;
    CryptoStream cs = new CryptoStream(ms, rjdAlg.CreateEncryptor(), CryptoStreamMode.Write);
    byte[] keyBytes = System.Text.Encoding.Unicode.GetBytes(keyParam.ToString());
    cs.Write(keyBytes, 0, keyBytes.Length);
    cs.Close();
    byte[] encryptedData = ms.ToArray();
    return encryptedData;
}

显然keyBytes设置在哪里我转换keyParam.ToString()是不正确的,因为它仅将KeyParameter的名称,而不是实际的价值。我提交这个功能之前的关键对返回的钥匙。私人的。

另一个问题是因为我不是加密的公用钥匙什么的格式应当我被储存在这个SQL2008数据库,(256)或者其他的?

任何帮助,将不胜感激。

有帮助吗?

解决方案

原因,应该是明确的,默认(或许无意中)化不播以及与私人钥匙应该只能写出在非常有限的情况。

BouncyCastle支持,8,其有关标准"列化"私人钥匙。有ASN。1的结构,称为PrivateKeyInfo和EncryptedPrivateKeyInfo.因为他们是在ASN。1有标准的方式serialize/deserialize他们。正如其名称所暗示的,一个商店的钥匙在明,其他加密钥的基础上密码。

对于公共钥匙-这些不一般都是加密的。BC支持X.509标准格式的SubjectPublicKeyInfo序列化他们。

在C#建立,高级别类来看将是:

  • Org.BouncyCastle.安全。PrivateKeyFactory
  • Org.BouncyCastle.安全。PublicKeyFactory
  • Org.BouncyCastle.详.EncryptedPrivateKeyInfoFactory
  • Org.BouncyCastle.详.PrivateKeyInfoFactory
  • Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory

其他提示

只要对象标记为可序列化,到对象转换为字节阵列的一个方法是使用BinaryFormatter类在.NET。

您需要这个using语句添加到您的代码文件:

using System.Runtime.Serialization.Formatters.Binary;

一个二进制格式化可以输出你的类的流。如要将您的对象转换为一个字节数组,可以用一个System.IO.MemoryStream作为临时存储。

MemoryStream memStream = new MemoryStream();

可以然后创建新的二进制格式化。

BinaryFormatter formatter = new BinarryFomatter();

和使用此序列化的对象。

formatter.Serialize(memStream, someObject);

要获得字节你可以使用:

return memStream.ToArray();

要反序列化字节数组需要将字节写入存储流。

memStream.Write(arrBytes, 0, arrBytes.Length);

返回流的开始。

memStream.Seek(0, SeekOrigin.Begin);

然后,使用格式化器重新创建该对象。

Object obj = (Object)formatter.Deserialize(memStream);

如果您已经使用加密函数你应该能够将所创建的字节数组将其存储在数据库中之前很容易地进行加密。

希望这将帮助您在正确的方向。如果你是幸运的,BouncyCastle的对象将被标记为可序列化,如果不是你将需要一些额外的代码。后来,我将有机会来看看BouncyCastle的图书馆的是能够测试这一点,并在必要时将发布更多的代码。


...我从来没有使用过BouncyCastle的。经过一些测试,看来该公钥和私钥对象不是序列化的,所以你需要将这些对象转换为东西是!

看来,公钥和私钥公开属性各种BouncyCastle.Math.BigInteger值。 (这些键也可以从这些BigIntegers来构造)。此外,BigIntegers具有ToByteArray()函数,并且还可以从一个字节数组构成。非常有用..

知道你可以打破每个钥匙插入BigIntegers和这些依次为一个字节数组,并且反过来也是可能的,则存储所有这些在一个可序列化对象的一种方式。一个简单的结构或类会做e.g。

[Serializable]
private struct CipherPrivateKey
{
    public byte[] modulus;
    public byte[] publicExponent;
    public byte[] privateExponent;
    public byte[] p;
    public byte[] q;
    public byte[] dP;
    public byte[] dQ;
    public byte[] qInv;
}

[Serializable]
private struct CipherPublicKey
{
    public bool isPrivate;
    public byte[] modulus;
    public byte[] exponent;
}

这为我们提供了对容易使用可序列化的对象。

在AsymmetricCipherKeyPair暴露公共及私人密钥为AsymmetricKeyParameter对象。要获取更详细的属性,你需要转换这些为以下内容:

keyPair.Public到BouncyCastle.Crypto.Parameters.RsaKeyParameters keyPair.Private到BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters

以下功能将这些转换为结构到前面声明:

private static CipherPublicKey getCipherPublicKey(Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters cPublic)
{
    CipherPublicKey cpub = new CipherPublicKey();
    cpub.modulus = cPublic.Modulus.ToByteArray();
    cpub.exponent = cPublic.Exponent.ToByteArray();
    return cpub;
}
private static CipherPrivateKey getCipherPrivateKey(Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters cPrivate)
{
    CipherPrivateKey cpri = new CipherPrivateKey();
    cpri.dP = cPrivate.DP.ToByteArray();
    cpri.dQ = cPrivate.DQ.ToByteArray();
    cpri.modulus = cPrivate.Modulus.ToByteArray();
    cpri.p = cPrivate.P.ToByteArray();
    cpri.privateExponent = cPrivate.Exponent.ToByteArray();
    cpri.publicExponent = cPrivate.PublicExponent.ToByteArray();
    cpri.q = cPrivate.Q.ToByteArray();
    cpri.qInv = cPrivate.QInv.ToByteArray();
    return cpri;
}

使用二进制格式化前面提到的,我们可以将我们就创建了一个字节数组的序列化的对象。

CipherPublicKey cpub = getCipherPublicKey((Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters)keypair.Public);
MemoryStream memStream = new MemoryStream();
BinaryFormatter formatter = new BinarryFomatter();
formatter.Serialize(memStream, cpub);
return memStream.ToArray();

Desierializing然后只是逆如前所述。一旦你有公共或私人结构反序列化可以使用BouncyCastle的contructors重建的关键。这些功能证明这一点。

private static Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters recreateASymCipherPublicKey(CipherPublicKey cPublicKey)
{
    Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters key;
    key = new Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters(
            cPublicKey.isPrivate,
            createBigInteger(cPublicKey.modulus),
            createBigInteger(cPublicKey.exponent));
    return key;
}

private static Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters recreateASymCipherPrivateKey(CipherPrivateKey cPrivateKey)
{
    Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters key;
    key = new Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters(
            createBigInteger(cPrivateKey.modulus),
            createBigInteger(cPrivateKey.publicExponent),
            createBigInteger(cPrivateKey.privateExponent),
            createBigInteger(cPrivateKey.p),
            createBigInteger(cPrivateKey.q),
            createBigInteger(cPrivateKey.dP),
            createBigInteger(cPrivateKey.dQ),
            createBigInteger(cPrivateKey.qInv));
    return key;
}

如果您需要重新创建任何原因原始密钥对:

AsymmetricKeyParameter publ = (AsymmetricKeyParameter)recreateASymCipherPublicKey(cKeyPair.publicKey);
AsymmetricKeyParameter priv = (AsymmetricKeyParameter)recreateASymCipherPrivateKey(cKeyPair.privateKey);
AsymmetricCipherKeyPair keyPair = new AsymmetricCipherKeyPair(publ, priv);

希望这一切才有意义!该代码示例应该帮助你对你的方式。

正确的做法是使用Peters的建议。

我已经包括以下一个小的C#代码示例:

var keyPair = GetKeypair();

PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);                        
byte[] serializedKey = privateKeyInfo.ToAsn1Object().GetDerEncoded();

AsymmetricKeyParameter deserializedKey1 = PrivateKeyFactory.CreateKey(serializedKey);
Assert.AreEqual(keyPair.Private, deserializedKey1);

AsymmetricKeyParameter deserializedKey2 = PrivateKeyFactory.CreateKey(privateKeyInfo);            
Assert.AreEqual(keyPair.Private, deserializedKey2);

该示例使用充气城堡API。 注意该样品不加密密钥。该CreatePrivateKeyInfo方法被重载以允许使用密码作为密钥的保护。

关于你的问题,应当使用用于存储密钥将是VARBINARY数据类型的第二部分(256)。

回到你的问题的第一部分,你实际上有其SQL Server的处理加密你的选择。当然,你是否会想这样做,将是您的应用需求是什么问题,但我会去在它的情况下,它是一个选项。

我们会非常基本的这里,只使用对称密钥和Triple-DES。

首先,数据库具有用于保护证书和非对称密钥的主密钥。主密钥进行加密,三重DES。

CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'supersecretpassword'  

的SQL Server 2005/2008可以生成用自己的X.509证书来保护用于加密的实际数据的密钥。

CREATE CERTIFICATE ExampleCertificate 
     WITH SUBJECT = 'thisisjustsomemetadata'

有很多用于加密对称密钥(证书,密码,其他键),以及许多支持的算法的选择。但在这个例子中,我们将使用证书。

CREATE SYMMETRIC KEY ExampleKey
     WITH ALGORITHM = TRIPLE_DES  
     ENCRYPTION BY CERTIFICATE EncryptTestCert 
使用与它加密的相同的方法进行解密

的关键需求。就我们而言,这将是我们创建的证书。

 DECLARE @Value VARCHAR(50)
 SET @Value = 'supersecretdata!'

 OPEN SYMMETRIC KEY ExampleKey DECRYPTION BY CERTIFICATE ExampleCertificate  
     UPDATE SomeTable  
     SET SomeColumn = ENCRYPTBYKEY(KEY_GUID('ExampleKey'), @Value)

解密同样也很简单。

OPEN SYMMETRIC KEY ExampleKey DECRYPTION BY CERTIFICATE ExampleCertificate  
     SELECT CONVERT(VARCHAR(50),DECRYPTBYKEY(SomeColumn)) AS DecryptedData 
     FROM SomeTable 

希望这解决您的问题,或至少打开你到其他解决方案(虽然有人谁是有在C#应用经验做加密或许可以找到你上面的代码错误)。如果有必要,该数据甚至不能去通过线路以纯文本的SQL服务器的要求,显然这是一个没有去(当然,你的可以的实际创建于SSL连接SQL服务器...)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top