Java asymmetrische Verschlüsselung: bevorzugte Art und Weise zu speichern, öffentliche / private Schlüssel

StackOverflow https://stackoverflow.com/questions/3441501

Frage

Dieser Code erzeugt ein Paar öffentlicher / privater Schlüssel:

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPair keypair = keyGen.genKeyPair();
PrivateKey privateKey = keypair.getPrivate();
PublicKey publicKey = keypair.getPublic();

Was ich möchte wissen, ist, wie Sie in der Regel den öffentlichen Schlüssel gespeichert werden:

Option 1: Speichern der Bytes

byte[] privateKeyBytes = privateKey.getEncoded();
byte[] publicKeyBytes = publicKey.getEncoded();
// ... write to file

// convert bytes back to public/private keys
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);

EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

Was ich nicht mag, ist, den Code zu konkreten Implementierungen wie PKCS8EncodedKeySpec und X509EncodedKeySpec zu binden.

Option 2: Speichern des Moduls und der Exponent

KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = fact.getKeySpec(publicKey, RSAPublicKeySpec.class);
RSAPrivateKeySpec priv = fact.getKeySpec(privateKey,RSAPrivateKeySpec.class);

// store modulus and exponent as BigIntegers
BigInteger modulus = pub.getModulus());
BigInteger exponent = pub.getPublicExponent());
// ... write to file

// recreate public key (the same applies to the private key)
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);

Die zweite Option ist einfacher zu implementieren, aber ich weiß nicht, ob es weniger performant sein könnte.

Jede beraten?

War es hilfreich?

Lösung

In unseren Anwendungen speichern wir öffentliche und private Schlüssel im DER-Format, so dass sie verwendet werden kann und außerhalb Java leichter manipuliert werden kann. In unserem Fall haben die privaten Schlüssel nicht Passwörter auf sie.

Um den privaten Schlüssel zu etwas leichter nutzbar in Java umwandeln:

openssl pkcs8 -topk8 -nocrypt -in key.pem -inform PEM -out key.der -outform DER

Dann können Sie einen privaten RSA-Schlüssel erhalten Sie direkt von:

public static RSAPrivateKey getPrivateKey(File privateKeyFile) throws IOException, GeneralSecurityException {
    byte[] keyBytes = new byte[(int)privateKeyFile.length()];
    FileInputStream fis = new FileInputStream(privateKeyFile);
    fis.read(keyBytes);
    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(spec);
    return privKey;
}

Der öffentliche Schlüssel ist ähnlich:

openssl rsa -in private.pem -pubout -outform DER -out public.der

und es zu lesen:

public static RSAPublicKey getPublicKey(File publicKeyFile) throws IOException, GeneralSecurityException {
    byte[] keyBytes = new byte[(int)publicKeyFile.length()];
    FileInputStream fis = new FileInputStream(publicKeyFile);
    fis.read(keyBytes);
    X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory factory = KeyFactory.getInstance("RSA");
    RSAPublicKey pubKey = (RSAPublicKey)factory.generatePublic(publicKeySpec);
    return pubKey;
}

speichern Viele Menschen dann Schlüsselspeicher. Für unsere Zwecke brauchten wir die gleichen Schlüssel über mehrere Anwendungen in verschiedenen Sprachen gemeinsam genutzt werden, und wollten nicht die Dateien auf der Festplatte kopieren.

In jedem Fall sollte die Leistung nicht eine große Sorge, weil Sie diese Schlüssel in einer Art von Singleton oder Cache wahrscheinlich zu speichern sind, anstatt sie jedes Mal zu regenerieren.

Andere Tipps

Sie speichern tatsächlich das Bytes in beiden Fällen, ob Sie es wahrhaben will oder nicht. Ich nehme an, die richtige Antwort auf in @ Brian M. Carr Antwort angedeutet, der das übergeordnete Objekt in seiner natürlichsten Form zu speichern ist. Im Fall von öffentlichen Schlüsseln sind die offensichtliche Wahl als PKCS # 1 RSAPublicKey ASN.1 Struktur, DIE-codierte oder als X509 SubjectPublicKeyInfo ASN.1 Struktur, DIE-kodiert. Letzteres ist das, was die Sun-Anbieter geben Ihnen, die die Sonne Klasse X509EncodedKeySpec unterstützt. Ebenso unterstützt die PKCS8EncodedKeySpec einen privaten Schlüssel Format. Beide Formate sind Normen und werden von OpenSSL beispielsweise unterstützt. Sun neigt - neigten :( -. Zu bestehenden Standards zu unterstützen eher dann ihre eigenen definieren

Wenn Sie ein Format für die Speicherung der Schlüssel definieren wollen, dann würde ich ein Format wählen, das so entbehrlich ist, dass es nicht bricht, wenn Sie ändern mögen Verschlüsselung (wenn die alten zum Beispiel zu schwach wird).

Also ich würde speichern die Bytes als base64 codiert, zusammen mit einer Zeichenfolge, die das Format beschreibt, „rsa“ vielleicht.

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