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?
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");
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;
}
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
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:
-
*.getEncoded (): https://docs.oracle.com/javase/7/docs/api/java/security/Key.html
-
informations sur L'encodeur: https://docs.oracle.com/javase/8/docs/api/java/util/Base64.Encoder.html
-
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");
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");
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;
}