web-dev-qa-db-fra.com

Conversion de la clé secrète en chaîne et vice-versa

Je génère une clé et je dois la stocker dans une base de données. Je la convertis donc en chaîne, mais je récupère la clé de la chaîne. Quels sont les moyens possibles pour y parvenir?

Mon code est,

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

Comment puis-je récupérer la clé de la chaîne?

76
Princeyesuraj

Vous pouvez convertir la variable SecretKey en un tableau d'octets (byte[]), puis l'encoder en Base64 en une variable String. Pour reconvertir en une SecretKey, Base64 décode la chaîne et l'utilise dans une SecretKeySpec pour reconstruire votre SecretKey d'origine.

Pour Java 8

SecretKey to String:

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

Chaîne vers 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"); 

Pour Java 7 et versions antérieures (y compris Android):

NOTE I: vous pouvez ignorer la partie encodage/décodage Base64 et simplement stocker le byte[] dans SQLite. Cela dit, le codage/décodage Base64 n’est pas une opération onéreuse et vous pouvez stocker des chaînes dans presque toutes les bases de données sans problème.

NOTE II: Les versions antérieures de Java n'incluent pas de Base64 dans l'un des packages Java.lang ou Java.util. Il est toutefois possible d’utiliser des codecs de Apache Commons Codec , Bouncy Castle ou Goyave .

SecretKey to 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)}

Chaîne vers 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

Pour montrer à quel point il est amusant de créer des fonctions qui sont échouent rapidement j'ai écrit les 3 fonctions suivantes.

On crée une clé AES, on la code et l’autre la décode. Ces trois méthodes peuvent être utilisées avec Java 8 (sans dépendance de classes internes ni de dépendances externes):

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

Vous ne voulez pas utiliser .toString()

Notez que SecretKey hérite de Java.security.Key, qui hérite lui aussi de Serializable. Donc, la clé ici (sans jeu de mots) est de sérialiser la clé dans un ByteArrayOutputStream, d’obtenir le tableau byte [] et de le stocker dans la base de données. Le processus inverse consisterait à extraire le tableau byte [] de la base de données, à créer un ByteArrayInputStream offf le tableau byte [] et à désérialiser la clé secrète ...

... ou même plus simple, utilisez simplement la méthode .getEncoded() héritée de Java.security.Key (qui est une interface parent de SecretKey). Cette méthode renvoie le tableau d'octets [] hors Key/SecretKey, que vous pouvez stocker ou extraire de la base de données.

Tout cela en supposant que votre implémentation SecretKey prenne en charge le codage. Sinon, getEncoded() retournera null.

modifier:

Vous devriez regarder les javadocs Key/SecretKey (disponibles au début d'une page Google):

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

Ou ceci de CodeRanch (également trouvé avec la même recherche de Google):

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

1
luis.espinal

Conversion de SecretKeySpec en String et inversement: Vous pouvez utiliser la méthode getEncoded() dans SecretKeySpec qui donnera byteArray, à partir de laquelle vous pouvez utiliser encodeToString() pour obtenir la valeur string de SecretKeySpec dans Base64 objet.

Lors de la conversion de SecretKeySpec en String: utiliser decode() dans Base64 donnera byteArray, à partir de laquelle vous pouvez créer une instance pour SecretKeySpec avec les paramètres comme byteArray pour reproduire votre SecretKeySpec.

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

En fait, ce que Luis a proposé n'a pas fonctionné pour moi. Je devais trouver un autre moyen. C'est ce qui m'a aidé. Pourrait vous aider aussi. Liens:

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

  2. Informations sur le codeur: https://docs.Oracle.com/javase/8/docs/api/Java/util/Base64.Encoder.html

  3. Informations du décodeur: https://docs.Oracle.com/javase/8/docs/api/Java/util/Base64.Decoder.html

Extraits de code: Pour l'encodage:

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

Pour le décodage:

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