Come posso convertire una stringa in una SecretKey

Voglio convertire String in secretKey

public void generateCode(String keyStr){ KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); // 192 and 256 bits may not be available // Generate the secret key specs. secretKey skey=keyStr; //How can I make the casting here //SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded(); } 

Provo ad usare BASE64Decoder invece di secretKey, ma devo affrontare un problema che non riesco a specificare la lunghezza della chiave.

EDIT: voglio chiamare questa funzione da un altro posto

  static public String encrypt(String message , String key , int keyLength) throws Exception { // Get the KeyGenerator KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(keyLength); // 192 and 256 bits may not be available // Generate the secret key specs. SecretKey skey = key; //here is the error byte[] raw = skey.getEncoded(); SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); // Instantiate the cipher Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, skeySpec); System.out.println("msg is" + message + "\n raw is" + raw); byte[] encrypted = cipher.doFinal(message.getBytes()); String cryptedValue = new String(encrypted); System.out.println("encrypted string: " + cryptedValue); return cryptedValue; } 

Se qualcuno potesse aiutare, sarei molto grato.

Nessun controllo di integrità, per queste particolari ragioni

  1. Il bisogno non è evidente dal caso d’uso.
  2. "AES/GCM/NoPadding" è disponibile solo da Java 7 in poi
  3. Dipende dall’utilizzatore se lo desidera implementare, ad esempio HMAC e / o AESCMAC (consigliato).
  4. Richiederebbe una chiave aggiuntiva al minimo e due passaggi completi.

Se hai un’implementazione della modalità GCM su entrambi i lati, ad esempio utilizzando Bouncy Castle su Java 6, ti preghiamo di farlo, poiché è molto più sicuro (a patto che la “IV” sia davvero unica). Dovrebbe essere davvero facile cambiare l’implementazione.

Note di implementazione relative alla crittografia

  1. Questa implementazione non è sicura se utilizzata in un ruolo client / server senza limitazioni a causa degli attacchi oracle di riempimento (richiedono in media 128 tentativi per byte o inferiore, indipendentemente dall’algoritmo o dalla dimensione della chiave). Sarà necessario utilizzare un MAC, HMAC o firma sui dati crittografati e verificarlo prima di decodificare per distribuirlo in modalità client / server.
  2. Decifrare restituirà null se la decifrazione fallisce. Questo può solo indicare un’eccezione di padding, che dovrebbe essere gestita in modo adeguato (ho avvertito circa il riempimento degli attacchi di Oracle?)
  3. Le chiavi non valide verranno restituite come InvalidArgumentException .
  4. Tutte le altre eccezioni relative alla sicurezza sono “trascinate sotto la tabella” in quanto significa che l’ambiente di runtime Java non è valido. Ad esempio, è richiesto il supporto di "UTF-8" e "AES/CBC/PKCS5Padding" per ogni implementazione di Java SE.

Alcune altre note

  1. Si prega di non provare il contrario e inserire i byte direttamente nella stringa di input del metodo di crittografia (utilizzando la new String(byte[]) per esempio). Il metodo potrebbe fallire silenziosamente!
  2. Ottimizzato per la leggibilità. CipherStream implementazioni di stream Base64 e CipherStream se preferisci la velocità e l’impronta della memoria.
  3. È necessario almeno Java 6 SE o compatibile per eseguire questo codice.
  4. La crittografia / decrittografia potrebbe non riuscire per le dimensioni delle chiavi AES superiori a 128 bit poiché potrebbero essere necessari file di criteri per la crittografia illimitata (disponibile da Oracle)
  5. Fai attenzione ai regolamenti governativi durante l’esportazione della crittografia.
  6. Questa implementazione utilizza chiavi esadecimali anziché basi64 perché sono abbastanza piccole e hex è più semplice da modificare / verificare manualmente.
  7. La codifica / decodifica hex e base64 recuperata dal JDK non richiede alcuna libreria esterna.
  8. Uber semplice da usare, ma ovviamente non molto orientato agli oggetti, nessuna memorizzazione nella cache delle istanze di oggetti usate in encrypt / decrypt. Refactor a volontà.

OK, ecco che arriva del codice …

  public static String encrypt(final String plainMessage, final String symKeyHex) { final byte[] symKeyData = DatatypeConverter.parseHexBinary(symKeyHex); final byte[] encodedMessage = plainMessage.getBytes(Charset .forName("UTF-8")); try { final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); final int blockSize = cipher.getBlockSize(); // create the key final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES"); // generate random IV using block size (possibly create a method for // this) final byte[] ivData = new byte[blockSize]; final SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG"); rnd.nextBytes(ivData); final IvParameterSpec iv = new IvParameterSpec(ivData); cipher.init(Cipher.ENCRYPT_MODE, symKey, iv); final byte[] encryptedMessage = cipher.doFinal(encodedMessage); // concatenate IV and encrypted message final byte[] ivAndEncryptedMessage = new byte[ivData.length + encryptedMessage.length]; System.arraycopy(ivData, 0, ivAndEncryptedMessage, 0, blockSize); System.arraycopy(encryptedMessage, 0, ivAndEncryptedMessage, blockSize, encryptedMessage.length); final String ivAndEncryptedMessageBase64 = DatatypeConverter .printBase64Binary(ivAndEncryptedMessage); return ivAndEncryptedMessageBase64; } catch (InvalidKeyException e) { throw new IllegalArgumentException( "key argument does not contain a valid AES key"); } catch (GeneralSecurityException e) { throw new IllegalStateException( "Unexpected exception during encryption", e); } } public static String decrypt(final String ivAndEncryptedMessageBase64, final String symKeyHex) { final byte[] symKeyData = DatatypeConverter.parseHexBinary(symKeyHex); final byte[] ivAndEncryptedMessage = DatatypeConverter .parseBase64Binary(ivAndEncryptedMessageBase64); try { final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); final int blockSize = cipher.getBlockSize(); // create the key final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES"); // retrieve random IV from start of the received message final byte[] ivData = new byte[blockSize]; System.arraycopy(ivAndEncryptedMessage, 0, ivData, 0, blockSize); final IvParameterSpec iv = new IvParameterSpec(ivData); // retrieve the encrypted message itself final byte[] encryptedMessage = new byte[ivAndEncryptedMessage.length - blockSize]; System.arraycopy(ivAndEncryptedMessage, blockSize, encryptedMessage, 0, encryptedMessage.length); cipher.init(Cipher.DECRYPT_MODE, symKey, iv); final byte[] encodedMessage = cipher.doFinal(encryptedMessage); // concatenate IV and encrypted message final String message = new String(encodedMessage, Charset.forName("UTF-8")); return message; } catch (InvalidKeyException e) { throw new IllegalArgumentException( "key argument does not contain a valid AES key"); } catch (BadPaddingException e) { // you'd better know about padding oracle attacks return null; } catch (GeneralSecurityException e) { throw new IllegalStateException( "Unexpected exception during decryption", e); } } 

Uso:

  String plain = "Zaphod's just zis guy, ya knöw?"; String encrypted = encrypt(plain, "000102030405060708090A0B0C0D0E0F"); System.out.println(encrypted); String decrypted = decrypt(encrypted, "000102030405060708090A0B0C0D0E0F"); if (decrypted != null && decrypted.equals(plain)) { System.out.println("Hey! " + decrypted); } else { System.out.println("Bummer!"); } 

Ecco la versione che utilizza la class Base64 Util invece di DatatypeConverter

 public static String encrypt(final String plainMessage, final String symKeyHex) { final byte[] symKeyData = Base64.decode(symKeyHex,Base64.DEFAULT); final byte[] encodedMessage = plainMessage.getBytes(Charset .forName("UTF-8")); try { final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); final int blockSize = cipher.getBlockSize(); // create the key final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES"); // generate random IV using block size (possibly create a method for // this) final byte[] ivData = new byte[blockSize]; final SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG"); rnd.nextBytes(ivData); final IvParameterSpec iv = new IvParameterSpec(ivData); cipher.init(Cipher.ENCRYPT_MODE, symKey, iv); final byte[] encryptedMessage = cipher.doFinal(encodedMessage); // concatenate IV and encrypted message final byte[] ivAndEncryptedMessage = new byte[ivData.length + encryptedMessage.length]; System.arraycopy(ivData, 0, ivAndEncryptedMessage, 0, blockSize); System.arraycopy(encryptedMessage, 0, ivAndEncryptedMessage, blockSize, encryptedMessage.length); final String ivAndEncryptedMessageBase64 = Base64.encodeToString(ivAndEncryptedMessage,Base64.DEFAULT); return ivAndEncryptedMessageBase64; } catch (InvalidKeyException e) { throw new IllegalArgumentException( "key argument does not contain a valid AES key"); } catch (GeneralSecurityException e) { throw new IllegalStateException( "Unexpected exception during encryption", e); } } public static String decrypt(final String ivAndEncryptedMessageBase64, final String symKeyHex) { final byte[] symKeyData = Base64.decode((symKeyHex),Base64.DEFAULT); final byte[] ivAndEncryptedMessage = Base64.decode(ivAndEncryptedMessageBase64,Base64.DEFAULT); try { final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); final int blockSize = cipher.getBlockSize(); // create the key final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES"); // retrieve random IV from start of the received message final byte[] ivData = new byte[blockSize]; System.arraycopy(ivAndEncryptedMessage, 0, ivData, 0, blockSize); final IvParameterSpec iv = new IvParameterSpec(ivData); // retrieve the encrypted message itself final byte[] encryptedMessage = new byte[ivAndEncryptedMessage.length - blockSize]; System.arraycopy(ivAndEncryptedMessage, blockSize, encryptedMessage, 0, encryptedMessage.length); cipher.init(Cipher.DECRYPT_MODE, symKey, iv); final byte[] encodedMessage = cipher.doFinal(encryptedMessage); // concatenate IV and encrypted message final String message = new String(encodedMessage, Charset.forName("UTF-8")); return message; } catch (InvalidKeyException e) { throw new IllegalArgumentException( "key argument does not contain a valid AES key"); } catch (BadPaddingException e) { // you'd better know about padding oracle attacks return null; } catch (GeneralSecurityException e) { throw new IllegalStateException( "Unexpected exception during decryption", e); } } 

Solo un promemoria per coloro che ottengono un’eccezione di riempimento. Assicurati di utilizzare la lunghezza corretta della chiave. Suggerimento: guarda il post di Maarten: il suo esagono è esattamente 32;) Non è una coincidenza 🙂