只要对象被标记为可序列化,将对象转换为字节数组的一种方法是使用 .Net 中的 BinaryFormatter 类。
您需要将此 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 值。(也可以从这些 BigInteger 构造键)。此外,BigIntegers 有一个 ToByteArray() 函数,也可以从字节数组构造。很有用..
知道您可以将每个键分解为 BigIntegers,然后将它们分解为字节数组,并且反过来也是可能的,您可以将所有这些都存储在可序列化的对象中。一个简单的结构或类就可以了,例如
[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();
反序列化就是前面描述的反序列化。反序列化公共或私有结构后,您可以使用 BouncyCastle 构造函数重新创建密钥。这些函数证明了这一点。
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);
希望这一切都说得通!代码示例应该可以帮助您。