it-swarm.com.de

Geheime Schlüssel in einen String umwandeln und umgekehrt

Ich generiere einen Schlüssel und muss ihn in DB speichern, also konvertiere ich ihn in einen String, aber um den Schlüssel aus dem String zurückzuholen. Welche Möglichkeiten gibt es, um dies zu erreichen?

Mein Code lautet

SecretKey key = KeyGenerator.getInstance("AES").generateKey();
String stringKey=key.toString();
System.out.println(stringKey);

Wie kann ich den Schlüssel vom String zurückholen?

76
Princeyesuraj

Sie können SecretKey in ein Byte-Array (byte[]) konvertieren und dann Base64 in ein String codieren. Um wieder in ein SecretKey zu konvertieren, decodiert Base64 den String und verwendet ihn in einem SecretKeySpec, um das ursprüngliche SecretKey neu zu erstellen.

Für Java 8

SecretKey zu String:

// create new key
SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey();
// get base64 encoded version of the key
String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());

String zu SecretKey:

// decode the base64 encoded string
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
// rebuild key using SecretKeySpec
SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); 

Für Java 7 und früher (einschließlich Android):

NOTE I: Sie können den Base64-Codierungs-/Decodierungsteil überspringen und den byte[] einfach in SQLite speichern. Das Ausführen der Base64-Codierung Decodierung ist jedoch keine kostspielige Operation, und Sie können Zeichenfolgen in fast jeder Datenbank ohne Probleme speichern.

NOTE II: Frühere Java-Versionen enthalten kein Base64 in einem der Pakete Java.lang oder Java.util. Es ist jedoch möglich, Codecs aus/- Apache Commons Codec , Bouncy Castle oder Guava zu verwenden.

SecretKey zu String:

// CREATE NEW KEY
// GET ENCODED VERSION OF KEY (THIS CAN BE STORED IN A DB)

    SecretKey secretKey;
    String stringKey;

    try {secretKey = KeyGenerator.getInstance("AES").generateKey();}
    catch (NoSuchAlgorithmException e) {/* LOG YOUR EXCEPTION */}

    if (secretKey != null) {stringKey = Base64.encodeToString(secretKey.getEncoded(), Base64.DEFAULT)}

String zu SecretKey:

// DECODE YOUR BASE64 STRING
// REBUILD KEY USING SecretKeySpec

    byte[] encodedKey     = Base64.decode(stringKey, Base64.DEFAULT);
    SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
221
Jabari

Um zu zeigen, wie viel Spaß es macht, einige Funktionen zu erstellen, die Fail Fast sind, habe ich die folgenden 3 Funktionen geschrieben.

Man erstellt einen AES-Schlüssel, man codiert ihn und man dekodiert ihn zurück. Diese drei Methoden können mit Java 8 verwendet werden (ohne Abhängigkeit interner Klassen oder außerhalb von Abhängigkeiten):

public static SecretKey generateAESKey(int keysize)
        throws InvalidParameterException {
    try {
        if (Cipher.getMaxAllowedKeyLength("AES") < keysize) {
            // this may be an issue if unlimited crypto is not installed
            throw new InvalidParameterException("Key size of " + keysize
                    + " not supported in this runtime");
        }

        final KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(keysize);
        return keyGen.generateKey();
    } catch (final NoSuchAlgorithmException e) {
        // AES functionality is a requirement for any Java SE runtime
        throw new IllegalStateException(
                "AES should always be present in a Java SE runtime", e);
    }
}

public static SecretKey decodeBase64ToAESKey(final String encodedKey)
        throws IllegalArgumentException {
    try {
        // throws IllegalArgumentException - if src is not in valid Base64
        // scheme
        final byte[] keyData = Base64.getDecoder().decode(encodedKey);
        final int keysize = keyData.length * Byte.SIZE;

        // this should be checked by a SecretKeyFactory, but that doesn't exist for AES
        switch (keysize) {
        case 128:
        case 192:
        case 256:
            break;
        default:
            throw new IllegalArgumentException("Invalid key size for AES: " + keysize);
        }

        if (Cipher.getMaxAllowedKeyLength("AES") < keysize) {
            // this may be an issue if unlimited crypto is not installed
            throw new IllegalArgumentException("Key size of " + keysize
                    + " not supported in this runtime");
        }

        // throws IllegalArgumentException - if key is empty
        final SecretKeySpec aesKey = new SecretKeySpec(keyData, "AES");
        return aesKey;
    } catch (final NoSuchAlgorithmException e) {
        // AES functionality is a requirement for any Java SE runtime
        throw new IllegalStateException(
                "AES should always be present in a Java SE runtime", e);
    }
}

public static String encodeAESKeyToBase64(final SecretKey aesKey)
        throws IllegalArgumentException {
    if (!aesKey.getAlgorithm().equalsIgnoreCase("AES")) {
        throw new IllegalArgumentException("Not an AES key");
    }

    final byte[] keyData = aesKey.getEncoded();
    final String encodedKey = Base64.getEncoder().encodeToString(keyData);
    return encodedKey;
}
4
Maarten Bodewes

Sie möchten .toString() nicht verwenden. 

Beachten Sie, dass SecretKey von Java.security.Key erbt, das wiederum von Serializable erbt. Der Schlüssel hier (kein Wortspiel beabsichtigt) ist also, den Schlüssel in einen ByteArrayOutputStream zu serialisieren, das Byte [] -Array abzurufen und in der Datenbank zu speichern. Der umgekehrte Vorgang wäre, das Byte [] -Array aus der Datenbank zu holen, einen ByteArrayInputStream des Byte [] - Arrays zu erstellen und den SecretKey davon zu deserialisieren ...

... oder noch einfacher, verwenden Sie einfach die .getEncoded()-Methode, die von Java.security.Key (einer übergeordneten Schnittstelle von SecretKey) geerbt wurde. Diese Methode gibt das codierte Byte [] -Array von Key/SecretKey zurück, das Sie speichern oder aus der Datenbank abrufen können.

Dies alles setzt voraus, dass Ihre SecretKey-Implementierung die Kodierung unterstützt. Andernfalls gibt getEncoded() null zurück.

bearbeiten:

Sie sollten sich die Key/SecretKey-Javadocs ansehen (direkt zu Beginn einer Google-Seite verfügbar):

http://download.Oracle.com/javase/6/docs/api/Java/security/Key.html

Oder dies von CodeRanch (auch mit der gleichen Google-Suche gefunden):

http://www.coderanch.com/t/429127/Java/java/Convertion-between-SecretKey-String-or

1
luis.espinal

Konvertieren von SecretKeySpec in String und umgekehrt: Sie können die getEncoded()-Methode in SecretKeySpec verwenden, die byteArray enthält. Daraus können Sie encodeToString() verwenden, um den string-Wert von SecretKeySpec im Base64-Objekt zu erhalten.

Bei der Konvertierung von SecretKeySpec in String: verwenden Sie decode() in Base64byteArray. Daraufhin können Sie eine Instanz für SecretKeySpec mit den Parametern als byteArray erstellen, um Ihre SecretKeySpec zu reproduzieren.

String mAesKey_string;
SecretKeySpec mAesKey= new SecretKeySpec(secretKey.getEncoded(), "AES");

//SecretKeySpec to String 
    byte[] byteaes=mAesKey.getEncoded();
    mAesKey_string=Base64.encodeToString(byteaes,Base64.NO_WRAP);

//String to SecretKeySpec
    byte[] aesByte = Base64.decode(mAesKey_string, Base64.NO_WRAP);
    mAesKey= new SecretKeySpec(aesByte, "AES");
0
anand krish

Eigentlich hat das, was Luis vorgeschlagen hat, für mich nicht funktioniert. Ich musste einen anderen Weg finden. Das hat mir geholfen. Könnte dir auch helfen. Links:

  1. * .getEncoded (): https://docs.Oracle.com/javase/7/docs/api/Java/security/Key.html

  2. Informationen zum Encoder: https://docs.Oracle.com/javase/8/docs/api/Java/util/Base64.Encoder.html

  3. Informationen zum Decoder: https://docs.Oracle.com/javase/8/docs/api/Java/util/Base64.Decoder.html

Codeausschnitte: Für die Kodierung:

String temp = new String(Base64.getEncoder().encode(key.getEncoded()));

Zum Dekodieren:

byte[] encodedKey = Base64.getDecoder().decode(temp);
SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "DES");
0
Revanth Kumar