2010-08-09 6 views
10

Dieser Code erzeugt ein Paar von öffentlichen/privaten Schlüsseln:Java asymmetrische Verschlüsselung: bevorzugte Art und Weise öffentliche/private Schlüssel zu speichern

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

Was Ich mag würde wissen, wie Sie in der Regel die öffentlichen Schlüssel speichern:

Option 1: speichern die 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 mag den Code nicht auf konkrete Implementierungen wiezu binden istund X509EncodedKeySpec.

Option 2: das Modul speichern und 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 zu implementieren leichter, aber ich weiß nicht, ob es weniger performant sein könnte.

Irgendwelche Ratschläge?

Antwort

12

In unseren Anwendungen speichern wir öffentliche und private Schlüssel im DER-Format, so dass sie einfacher außerhalb von Java verwendet und bearbeitet werden können. In unserem Fall haben die privaten Schlüssel keine Passwörter.

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

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 pkcs8 -topk8 -nocrypt -in key.pem -inform PEM -out key.der -outform DER 

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

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

Viele Leute speichern dann Keystores. Für unsere Zwecke mussten wir den gleichen Schlüssel für mehrere Anwendungen in verschiedenen Sprachen verwenden und die Dateien auf der Festplatte nicht duplizieren.

In beiden Fällen sollte die Leistung keine große Rolle spielen, da Sie diese Schlüssel wahrscheinlich in einer Art Singleton oder Cache speichern, anstatt sie jedes Mal neu zu generieren.

+1

DER ist nicht wirklich ein Format per se, nur die Art und Weise ASN.1 Objekte zu kodieren. –

+0

Für diejenigen, die öffentlich werden wollen. direkt von 'id_rsa.pub' (öffentlicher Schlüssel) statt' id_rsa' (privater Schlüssel) [diese Antwort bietet eine Möglichkeit, das zu tun] (http://stackoverflow.com/a/18290786/813810). – Diego

1

Wenn Sie ein Format zum Speichern der Schlüssel definieren möchten, dann würde ich ein Format wählen, das entbehrlich ist, damit es nicht bricht, wenn Sie die Verschlüsselung ändern wollen (wenn das alte zum Beispiel zu schwach wird).

Also würde ich die Bytes als Base64 codiert, zusammen mit einer Zeichenfolge, die das Format beschreibt, "RSA" vielleicht.

2

Sie speichern die Bytes in beiden Fällen tatsächlich, ob Sie es erkennen oder nicht. Ich nehme an, die richtige Antwort ist in @ Brian M. Carr Antwort angedeutet, die das übergeordnete Objekt in seiner natürlichsten Form zu speichern ist. Im Fall von öffentlichen Schlüsseln sind die offensichtlichen Wahlmöglichkeiten eine PKCS # 1 RSAPublicKey ASN.1-Struktur, DER-codiert oder als eine X509 SubjectPublicKeyInfo ASN.1-Struktur, DER-codiert. Letzteres geben die Sun-Anbieter, die die Sonnenklasse X509EncodedKeySpec unterstützt. In ähnlicher Weise unterstützt PKCS8EncodedKeySpec ein privates Schlüsselformat. Beide Formate sind Standards und werden beispielsweise von openssl unterstützt.Sun tend - tended :(- um existierende Standards zu unterstützen anstatt eigene zu definieren.

+0

Danke Sie wirklich hilfreich.Ich markiere @Brian M. Carr Antwort als akzeptiert, weil die Codebeispiele. –