Шифрование Пары ключей BouncyCastle RSA и хранение в базе данных SQL2008

В JSBin, на которую вы ссылались, вы не импортировали jQuery, но, похоже, вы используете селектор jQuery для установки содержимого элементов DOM #skip-result и #distinct-result. Это выдаст ошибку.

Если вместо этого вы изменили их, установив свойство innerHTML, которое, по-видимому, уже делает одна подписка, вы должны получить ожидаемое поведение.

.subscribe(s => {
  skipResult.innerHTML = 'Skip Value is ' + s
})

РЕДАКТИРОВАТЬ

После второго просмотра ваша разметка закрывается неправильно. В частности, #skip-result делается потомком #distinct-result.

5
задан TravisPUK 10 May 2009 в 09:21
поделиться

3 ответа

по причинам, которые должны быть четкими, по умолчанию (и, возможно, непреднамеренному) сериализацию не играют хорошо с частными ключами, которые следует записать только в очень ограниченных ситуациях.

BounCactcle имеет поддержку PKCS # 8, что является соответствующим стандартом для «сериализации» частных клавиш. Существуют структуры ASN.1, называемые PowningKeyInfo и EncryptedPrivateKeyInfo. Поскольку они находятся в ASN.1, есть стандартные способы для их сериализации / десериализации. Как предполагает имя, он хранит ключ в открытом тексте, другой шифрует ключ на основе пароля.

Для открытых ключей - они обычно не будут зашифрованы. BC поддерживает стандартный формат X.509 в соответствии с CusticSublicKeyInfo для их сериализации.

В строительстве C #, классы высокого уровня, чтобы посмотреть, будет:

  • org.bouncycectle.security.PrivateKeyFactory
  • org.bouncectlet.security.publickeficifactory
  • org.bouncectle.pkcs.encryptedPrivateKeyInfofactory
  • org.bouncycectle.pkcs.privateKeyInfofactory
  • org.bouncycastle.x509.subjectpublickeyinfofactory
17
ответ дан 18 December 2019 в 05:29
поделиться

Пока объект помечен как сериализуемый, одним из способов преобразования объекта в байтовый массив является использование класса BinaryFormatter в .Net.

Вам нужно будет добавить это, используя в файл кода:

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 () и также могут быть созданы из массива байтов. Очень полезно ..

Зная, что вы можете разбить каждый ключ на BigInteger, а они, в свою очередь, на массив байтов, и что обратное тоже возможно, вы можете сохранить все это в сериализуемом объекте. Подойдет простая структура или класс, например

[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

Зная, что вы можете разбить каждый ключ на BigInteger, а они, в свою очередь, на массив байтов, и что обратное также возможно, вы можете сохранить все это в сериализуемом объекте. Подойдет простая структура или класс, например

[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

Зная, что вы можете разбить каждый ключ на BigInteger, а они, в свою очередь, на массив байтов, и что обратное также возможно, вы можете сохранить все это в сериализуемом объекте. Подойдет простая структура или класс, например

[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;
}

Используя двоичный форматер, упомянутый ранее, мы можем преобразовать сериализуемые объекты, которые мы только что создали, в байтовые array.

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);

Надеюсь, все это имеет смысл! Примеры кода должны помочь вам на вашем пути.

11
ответ дан 18 December 2019 в 05:29
поделиться

Что касается второй части вашего вопроса, тип данных, который следует использовать для хранения ключа, будет VARBINARY (256).

Возвращаясь к первой части вашего вопроса, у вас действительно есть возможность иметь SQL Server обрабатывать шифрование за вас. Конечно, захотите вы это сделать или нет, будет зависеть от требований вашего приложения, но я рассмотрю это на случай, если это вариант.

Здесь мы будем довольно простыми и просто будем использовать симметричные ключи и Triple-DES.

Во-первых, база данных имеет главный ключ, который используется для защиты сертификатов и асимметричных ключей. Главный ключ зашифрован с помощью Triple-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 Server в виде обычного текста,

1
ответ дан 18 December 2019 в 05:29
поделиться