Frage

Ich habe eine Funktion, die ein BouncyCastle RSA-Schlüsselpaar erzeugt. Ich brauche den privaten Schlüssel zu verschlüsseln und speichern Sie dann die verschlüsselten privaten und öffentlichen Schlüssel in separate SQL2008 Datenbankfelder.

Ich bin mit dem im Anschluss an das Schlüsselpaar zu erhalten:

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

Dies kehrt der Schlüssel in Ordnung, aber ich bin nicht sicher, wie ich dann die privaten Schlüssel verschlüsseln und es anschließend in der Datenbank speichern.

Das ist, was ich zur Zeit die Daten verschlüsselt bin mit (falsch?):

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

Offensichtlich ist die Einstellung keyBytes, wo ich bin Umwandlung keyParam.ToString () ist nicht korrekt, da es nur den KeyParameter Namen konvertiert, nicht der tatsächliche Wert. Ich bin mit der vorherigen Schlüsselpaar Rückkehr von keys.Private zu dieser Funktion senden.

Die andere Frage ist, wie ich bin nicht der Public-Key-Verschlüsselung, welches Format sollte ich dies in der SQL2008 Datenbank, nvarchar (256) oder einem anderen?

werden die Speicherung

Jede Hilfe wäre sehr geschätzt.

War es hilfreich?

Lösung

Aus Gründen, die klar sein sollte, default (und vielleicht unbeabsichtigte) Serialisierung nicht gut mit privaten Schlüsseln nicht spielen, die nur in sehr wenigen Fällen ausgeschrieben werden sollte.

BouncyCastle hat die Unterstützung für PKCS # 8, die entsprechende Norm ist für private Schlüssel „Serialisierung“. Es gibt ASN.1 Strukturen PrivateKeyInfo und EncryptedPrivateKeyInfo genannt. Da sie in ASN.1 gibt es Standardmethoden sind sie zu serialisiert / deserialisiert. Wie der Name schon sagt, speichert man den Schlüssel im Klartext, die anderen die Schlüssel auf einem Passwort basieren verschlüsselt.

Für die öffentlichen Schlüssel - diese würden normalerweise nicht verschlüsselt werden. BC unterstützt das X.509-Standard-Format von SubjectPublicKeyInfo für sie Serialisierung.

In der C # zu bauen, die High-Level-Klassen zu betrachten wäre:

  • Org.BouncyCastle.Security.PrivateKeyFactory
  • Org.BouncyCastle.Security.PublicKeyFactory
  • Org.BouncyCastle.Pkcs.EncryptedPrivateKeyInfoFactory
  • Org.BouncyCastle.Pkcs.PrivateKeyInfoFactory
  • Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory

Andere Tipps

Solange das Objekt als serialisierbar gekennzeichnet ist, besteht eine Möglichkeit, ein Objekt zu einem Byte-Array zu konvertieren ist die BinaryFormatter-Klasse in .NET zu verwenden.

Sie müssen diese Anweisung using, um Ihre Code-Datei hinzuzufügen:

using System.Runtime.Serialization.Formatters.Binary;

Ein binäres Formatierungsprogramm ausgeben kann Ihre Klasse in einen Stream. Wie Sie beabsichtigen, Ihr Objekt zu einer Byte-Array zu konvertieren, können Sie ein System.IO.MemoryStream als Zwischenspeicher verwendet werden.

MemoryStream memStream = new MemoryStream();

Sie können dann erstellen Sie ein neues binäres Formatierungsprogramm.

BinaryFormatter formatter = new BinarryFomatter();

und verwendet das Ihr Objekt serialisiert werden.

formatter.Serialize(memStream, someObject);

Um das Bytes erhalten können Sie:

return memStream.ToArray();

den Byte-Array deserialisieren müssen Sie das Bytes in einem Speicher-Stream schreiben.

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

Zurück zum Anfang des Streams.

memStream.Seek(0, SeekOrigin.Begin);

Dann nutzen Sie die Formatierer das Objekt neu zu erstellen.

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

Wenn Sie bereits Verschlüsselungsfunktionen verwenden, sollten Sie die erstellte Byte-Array zu verschlüsseln ganz leicht in der Lage sein, bevor sie in der Datenbank zu speichern.

Wir hoffen, dass Sie in die richtige Richtung zu helfen. Wenn Sie Glück haben, werden die BouncyCastle Objekte als serialisierbar markiert, wenn nicht müssen Sie einige zusätzliche Code. Später werde ich die Chance bekommt, an dem BouncyCastle librarys zu suchen, um dies zu testen und mehr Code bei Bedarf erstellen.


... Ich habe BouncyCastle noch nie benutzt. Nach einigen Tests scheint es, dass die öffentlichen und privaten Schlüssel Objekte nicht serialisierbar sind, so dass Sie diese Objekte in etwas umwandeln müssen, das ist!

Es scheint, dass die öffentlichen und privaten Schlüssel Eigenschaften wie verschiedene BouncyCastle.Math.BigInteger Werte aus. (Die Tasten können auch aus diesem BigIntegers konstruiert werden). Ferner hat BigIntegers eine ToByteArray () Funktion und auch von einem Byte-Array aufgebaut werden kann. Sehr nützlich ..

Zu wissen, dass Sie jede Taste in BigIntegers und diese wiederum zu einem Byte-Array brechen können und dass umgekehrt ist auch möglich, Sie eine Möglichkeit, diese alle in einem serializable Objekt zu speichern. Eine einfache Struktur oder Klasse tun würde, z.

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

Das gibt uns ein Paar leicht serialisierbare Objekte zu verwenden.

Die AsymmetricCipherKeyPair macht die öffentlichen und privaten Schlüssel als AsymmetricKeyParameter Objekte. Um bei den detaillierteren Eigenschaften müssen Sie diese an folgenden werfen:

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

Folgende Funktionen werden diese an die structs zu erklären früher umwandeln:

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

Mit dem binären Formatter bereits erwähnt, können wir die serialisierbare Objekte konvertieren wir in einem Byte-Array gerade erstellt haben.

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 ist dann nur die inverse wie oben beschrieben. Sobald Sie haben entweder die öffentlichen oder privaten structs deserialisiert können Sie die BouncyCastle contructors verwenden, um die Schlüssel neu zu erstellen. Diese Funktionen zeigen dies.

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

Wenn Sie das Original-Schlüsselpaar aus irgendeinem Grunde neu zu erstellen:

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

Hoffentlich macht alles Sinn! Die Codebeispiele sollten Sie auf Ihrem Weg helfen.

Der richtige Ansatz ist Peters' Vorschlag zu verwenden.

Ich habe ein kleines C # Codebeispiel unten enthalten:

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

Das Beispiel verwendet die Hüpfburg API. Hinweis , dass die Probe den Schlüssel nicht verschlüsseln. Die CreatePrivateKeyInfo Methode ist überlastet die Verwendung eines Passworts zum Schutz des Schlüssels zu ermöglichen.

In Bezug auf den zweiten Teil Ihrer Frage, die Datentyp, der zum Speichern der Schlüssel verwendet werden sollte, wäre VARBINARY (256).

Zum ersten Teil Ihrer Frage, Sie haben tatsächlich die Möglichkeit, SQL Server von mit der Verschlüsselung für Sie. Zugegeben, ob Sie dies tun möchte, wäre eine Frage dessen, was die Anforderungen Ihrer Anwendung sind, aber ich werde darüber im Falle gehen, es ist eine Option.

Wir werden ziemlich einfach sein, hier und nur symmetrische Schlüssel verwenden und Triple-DIE.

Zuerst muss die Datenbank einen Hauptschlüssel, der verwendet wird, um Zertifikate und asymmetrische Schlüssel zu schützen. Der Hauptschlüssel wird verschlüsselt mit Triple-DEM.

CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'supersecretpassword'  

SQL Server 2005/2008 kann ihre eigenen X.509-Zertifikate verwendet, erzeugt die Schlüssel zum Schutz verwendet, um die tatsächlichen Daten zu verschlüsseln.

CREATE CERTIFICATE ExampleCertificate 
     WITH SUBJECT = 'thisisjustsomemetadata'

Es gibt eine Menge von Optionen für die Verschlüsselung von symmetrischen Schlüssel (Zertifikate, Passwörter, andere Schlüssel), sowie viele unterstützten Algorithmen. Aber für dieses Beispiel werden wir unser Zertifikat verwenden.

CREATE SYMMETRIC KEY ExampleKey
     WITH ALGORITHM = TRIPLE_DES  
     ENCRYPTION BY CERTIFICATE EncryptTestCert 

Die wichtigsten Anforderungen entschlüsselt werden nach dem gleichen Verfahren, mit dem sie verschlüsselt wurde. In unserem Fall wäre dies das Zertifikat werden wir erstellt haben.

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

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

Decryption ist genauso einfach.

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

Hoffentlich gelöst Ihr Problem, oder zumindest geöffnet Sie alternative Lösungen auf (obwohl jemand, die Erfahrung zu tun Verschlüsselung in C # Anwendungen gehabt hat könnte wahrscheinlich den Fehler in Ihrem obigen Code finden). Wenn Sie Anforderungen haben, die erfordern, dass die Daten nicht einmal über den Draht zu der SQL Server in Klartext gehen kann, ist dies offensichtlich ein No-Go (na ja, Sie können erstellen tatsächlich SSL-Verbindungen SQL Server ...).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top