Conversion D'une clé secrète en une chaîne et Vice Versa

je génère une clé et j'ai besoin de la stocker dans DB, donc je la transforme en une chaîne, mais pour récupérer la clé de la chaîne. Quels sont les moyens possibles pour arriver à ce résultat?

mon code est,

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

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

72
demandé sur dseibert 2011-03-18 20:09:37

6 réponses

vous pouvez convertir le SecretKey en un tableau d'octets ( byte[] ), puis Base64 Encoder cela en un String . Pour revenir à un SecretKey , Base64 décoder la Chaîne et l'utiliser dans un SecretKeySpec pour reconstruire votre original SecretKey .

Pour Java 8

SecretKey à la Chaîne:

// 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 à 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 avant (y compris Android):

NOTE I: vous pouvez sauter la partie d'encodage/décodage Base64 et simplement stocker le byte[] en SQLite. Cela dit, effectuer L'encodage/décodage Base64 n'est pas une opération coûteuse et vous pouvez stocker des chaînes dans presque n'importe quelle base de données sans problème.

NOTE II: les versions Java antérieures n'incluent pas une Base64 dans une des colis java.lang ou java.util . Il est cependant possible d'utiliser des codecs de Apache Commons Codec , château gonflable ou Guava .

SecretKey à la Chaîne:

// 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 à 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");
200
répondu Jabari 2014-12-21 19:28:20

pour montrer combien il est amusant de créer des fonctions qui sont fail fast j'ai écrit les 3 fonctions suivantes.

On crée une clé AES, on l'encode et décode un retour. Ces trois méthodes peuvent être utilisées avec Java 8 (sans dépendance des classes internes ou des 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
répondu Maarten Bodewes 2014-12-21 23:07:36

Vous ne voulez pas utiliser .toString() .

notez que SecretKey hérite de java.sécurité.Clé, qui lui-même hérite de sérialisable. Donc la clé ici (sans jeu de mots) est de sérialiser la clé dans un ByteArrayOutputStream, obtenir le tableau byte[] et le stocker dans le db. Le processus inverse serait d'enlever le tableau byte[] du db, de créer un ByteArrayInputStream du tableau byte [], et de desérialiser la clé secrète...

... ou encore plus simple, il suffit d'utiliser la méthode .getEncoded() héritée de java.sécurité.Clé (qui est une interface parent de SecretKey). Cette méthode renvoie le tableau Byte encoded[] Off Key/SecretKey, que vous pouvez stocker ou récupérer à partir de la base de données.

tout cela suppose que votre implémentation de SecretKey supporte l'encodage. Sinon, getEncoded() retournera null.

edit:

vous devriez regarder la clé / secretkey javadocs (disponible dès le début d'une page google):

http://download.oracle.com/javase/6/docs/api/java/security/Key.html

ou cette de CodeRanch (également trouvé avec la même recherche sur google):

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

1
répondu luis.espinal 2011-03-18 17:19:44

en fait, ce que Luis a proposé n'a pas fonctionné pour moi. J'ai dû 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 L'encodeur: https://docs.oracle.com/javase/8/docs/api/java/util/Base64.Encoder.html

  3. informations sur le Décodeur: https://docs.oracle.com/javase/8/docs/api/java/util/Base64.Decoder.html

fragments de Code: Pour 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
répondu Revanth Kumar 2017-02-10 09:18:30

conversion de SecretKeySpec en chaîne et vice-versa: vous pouvez utiliser getEncoded() méthode SecretKeySpec qui donnera byteArray , que vous pouvez utiliser encodeToString() pour obtenir string valeur SecretKeySpec dans Base64 objet.

lors de la conversion de SecretKeySpec en String : utilisez decode() dans Base64 donnera byteArray , à partir de cela vous pouvez créer l'instance pour SecretKeySpec avec les params comme les 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
répondu anand krish 2017-09-19 01:02:07

essayez ceci, c'est un travail sans Base64 ( qui n'est inclus que dans JDK 1.8 ), ce code s'exécute aussi dans la version java précédente:)

private static String SK = "Secret Key in HEX";


//  To Encrupt

public static String encrypt( String Message ) throws Exception{

    byte[] KeyByte = hexStringToByteArray( SK);
    SecretKey k = new SecretKeySpec(KeyByte, 0, KeyByte.length, "DES");

    Cipher c = Cipher.getInstance("DES","SunJCE");
    c.init(1, k);
    byte mes_encrypted[] = cipher.doFinal(Message.getBytes());

    String MessageEncrypted = byteArrayToHexString(mes_encrypted);
    return MessageEncrypted;
}

//  To Decrypt

public static String decrypt( String MessageEncrypted )throws Exception{

    byte[] KeyByte = hexStringToByteArray( SK );
    SecretKey k = new SecretKeySpec(KeyByte, 0, KeyByte.length, "DES");

    Cipher dcr =  Cipher.getInstance("DES","SunJCE");
    dc.init(Cipher.DECRYPT_MODE, k);
    byte[] MesByte  = hexStringToByteArray( MessageEncrypted );
    byte mes_decrypted[] = dcipher.doFinal( MesByte );
    String MessageDecrypeted = new String(mes_decrypted);

    return MessageDecrypeted;
}

public static String byteArrayToHexString(byte bytes[]){

    StringBuffer hexDump = new StringBuffer();
    for(int i = 0; i < bytes.length; i++){
    if(bytes[i] < 0)
    {   
        hexDump.append(getDoubleHexValue(Integer.toHexString(256 - Math.abs(bytes[i]))).toUpperCase());
    }else
    {
        hexDump.append(getDoubleHexValue(Integer.toHexString(bytes[i])).toUpperCase());
    }
    return hexDump.toString();

}



public static byte[] hexStringToByteArray(String s) {

    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2)
    {   
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
    }
    return data;

} 
-1
répondu daniel 2017-03-17 16:27:16