AES (Advanced Encryption Standard) és un algorisme de xifratge de clau simètrica que s'utilitza
per xifrar i desxifrar informació sensible. Funciona prenent text pla com a entrada i aplicant
una sèrie de transformacions matemàtiques, o "rounds", mitjançant una clau secreta.
El resultat és un text xifrat, que és il·legible sense la clau.
El nombre de rondes i les operacions matemàtiques específiques utilitzades depenen de la mida de la clau;
AES pot utilitzar claus de 128 bits, 192 bits o 256 bits.
L'objectiu d'AES és protegir la informació sensible, com ara números de targeta de crèdit i
credencials d'inici de sessió, de l'accés no autoritzat.
S'utilitza àmpliament en una varietat d'aplicacions, com ara compres en línia, banca en línia i comunicacions segures.
En Java podem generar una SecretKey utilitzant la
classe KeyGenerator, indicant l'algorisme que volem
utilitzar.
publicstaticSecretKeykeygenKeyGeneration(intkeySize){SecretKeysKey=null;if((keySize==128)||(keySize==192)||(keySize==256)){try{KeyGeneratorkgen=KeyGenerator.getInstance("AES");kgen.init(keySize);sKey=kgen.generateKey();}catch(NoSuchAlgorithmExceptionex){System.err.println("Generador no disponible.");}}returnsKey;}
També es pot utilitzar l'eina OpenSSL per generar la clau AES:
El següent mètode genera una SecretKey a partir
del hash SHA-256 d'una contrasenya.
publicstaticSecretKeypasswordKeyGeneration(Stringpassword,intkeySize){SecretKeysKey=null;if((keySize==128)||(keySize==192)||(keySize==256)){try{byte[]data=password.getBytes(StandardCharsets.UTF_8);MessageDigestmd=MessageDigest.getInstance("SHA-256");byte[]hash=md.digest(data);byte[]key=Arrays.copyOf(hash,keySize/8);sKey=newSecretKeySpec(key,"AES");}catch(Exceptionex){System.err.println("Error generant la clau:"+ex);}}returnsKey;}
L'algorisme AES serveix per xifrar i desxifrar dades.
Aquestes operacions es poden dur a terme a Java mitjançant la classe Cipher.
En el següent mètode, s'utilitza la classe Chiper per portar a terme
l'acció d'encriptar o desencriptar, indicada mitjançant el paràmetre int opmode.
Aquest paràmetre pot rebre els valors Cipher.ENCRYPT_MODE o Cipher.DECRYPT_MODE.
Si volem encriptar dades de tipus String, primer caldrà convertir-les
a byte[].
Podem crear un altre mètode "wrapper" per fer-ho:
publicstaticStringencrypt(SecretKeykey,Stringstr){try{// Decode the UTF-8 String into byte[] and encrypt itbyte[]data=encrypt(key,str.getBytes(StandardCharsets.UTF_8));// Encode the encrypted data into base64returnBase64.getEncoder().encodeToString(data);}catch(Exceptionex){System.err.println("Error xifrant les dades: "+ex);}returnnull;}
Si volem desencriptar dades de tipus String, primer caldrà convertir-les
a byte[].
Podem crear un altre mètode "wrapper" per fer-ho:
publicstaticStringdecrypt(SecretKeykey,Stringstr){try{// Decode the base64 encrypted string to a byte[]byte[]data=Base64.getDecoder().decode(str);// Decrypyt the byte[] databyte[]decrypted=decrypt(key,data);// Encode the decrypted data in a StringreturnnewString(decrypted);}catch(Exceptionex){System.err.println("Error desxifrant les dades: "+ex);}returnnull;}
Per guardar una clau privada en un fitxer,
sols cal codificar-la en base64 i guarda-la en
el fitxer.
publicstaticvoidsaveSecretKeyToFile(SecretKeykey,Stringpath)throwsIOException{// Base64 encode the keyStringencodedKey=Base64.getEncoder().encodeToString(key.getEncoded());// Write the key to a fileFiles.write(Paths.get(path),encodedKey.getBytes());}
Per carregar una clau privada des d'un fitxer,
sols cal llegir els continguts i crear l'objecte
SecretKey.
publicstaticSecretKeyloadSecretKeyFromFile(Stringpath)throwsIOException{// Read the key from fileStringfileContent=newString(Files.readAllBytes(Paths.get(path)));// Decode the base64 key into byte[]byte[]keyBytes=Base64.getDecoder().decode(fileContent);// Create the SecretKey objectreturnnewSecretKeySpec(keyBytes,"AES");}
Tot el codi font anteriorment proporcionat s'ha compilat
en la següent llibreria:
AES.java
packageud4.examples;importjavax.crypto.*;importjavax.crypto.spec.SecretKeySpec;importjava.io.IOException;importjava.nio.charset.StandardCharsets;importjava.nio.file.Files;importjava.nio.file.Paths;importjava.security.InvalidKeyException;importjava.security.MessageDigest;importjava.security.NoSuchAlgorithmException;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.Base64;publicclassAES{publicstaticSecretKeykeygenKeyGeneration(intkeySize){SecretKeysKey=null;if((keySize==128)||(keySize==192)||(keySize==256)){try{KeyGeneratorkgen=KeyGenerator.getInstance("AES");kgen.init(keySize);sKey=kgen.generateKey();}catch(NoSuchAlgorithmExceptionex){System.err.println("Generador no disponible.");}}returnsKey;}publicstaticSecretKeypasswordKeyGeneration(Stringpassword,intkeySize){SecretKeysKey=null;if((keySize==128)||(keySize==192)||(keySize==256)){try{byte[]data=password.getBytes(StandardCharsets.UTF_8);MessageDigestmd=MessageDigest.getInstance("SHA-256");byte[]hash=md.digest(data);byte[]key=Arrays.copyOf(hash,keySize/8);sKey=newSecretKeySpec(key,"AES");}catch(Exceptionex){System.err.println("Error generant la clau:"+ex);}}returnsKey;}publicstaticStringencrypt(SecretKeykey,Stringstr)throwsNoSuchPaddingException,IllegalBlockSizeException,NoSuchAlgorithmException,BadPaddingException,InvalidKeyException{// Decode the UTF-8 String into byte[] and encrypt itbyte[]data=encrypt(key,str.getBytes(StandardCharsets.UTF_8));// Encode the encrypted data into base64returnBase64.getEncoder().encodeToString(data);}publicstaticStringdecrypt(SecretKeykey,Stringstr)throwsNoSuchPaddingException,IllegalBlockSizeException,NoSuchAlgorithmException,BadPaddingException,InvalidKeyException{// Decode the base64 encrypted string to a byte[]byte[]data=Base64.getDecoder().decode(str);// Decrypyt the byte[] databyte[]decrypted=decrypt(key,data);// Encode the decrypted data in a StringreturnnewString(decrypted);}publicstaticbyte[]encrypt(SecretKeykey,byte[]data)throwsNoSuchPaddingException,IllegalBlockSizeException,NoSuchAlgorithmException,BadPaddingException,InvalidKeyException{returnaes(key,data,Cipher.ENCRYPT_MODE);}publicstaticbyte[]decrypt(SecretKeykey,byte[]data)throwsNoSuchPaddingException,IllegalBlockSizeException,NoSuchAlgorithmException,BadPaddingException,InvalidKeyException{returnaes(key,data,Cipher.DECRYPT_MODE);}privatestaticbyte[]aes(SecretKeykey,byte[]data,intopmode)throwsNoSuchPaddingException,NoSuchAlgorithmException,InvalidKeyException,IllegalBlockSizeException,BadPaddingException{Ciphercipher=Cipher.getInstance("AES");cipher.init(opmode,key);returncipher.doFinal(data);}publicstaticvoidsaveSecretKeyToFile(SecretKeykey,Stringpath)throwsIOException{// Base64 encode the keyStringencodedKey=Base64.getEncoder().encodeToString(key.getEncoded());// Write the key to a fileFiles.write(Paths.get(path),encodedKey.getBytes());}publicstaticSecretKeyloadSecretKeyFromFile(Stringpath)throwsIOException{// Read the key from fileStringfileContent=newString(Files.readAllBytes(Paths.get(path)));// Decode the base64 key into byte[]byte[]keyBytes=Base64.getDecoder().decode(fileContent);// Create the SecretKey objectreturnnewSecretKeySpec(keyBytes,"AES");}publicstaticvoidmain(String[]args)throwsNoSuchPaddingException,IllegalBlockSizeException,NoSuchAlgorithmException,BadPaddingException,InvalidKeyException{Stringmessage="Aquest és un missatge super secret";ArrayList<SecretKey>keys=newArrayList<>();Stringpassword="veryDifficultPassword";intkeySize=256;keys.add(passwordKeyGeneration(password,keySize));System.out.printf("Key generated with password: %s\n",password);keys.add(keygenKeyGeneration(keySize));for(SecretKeykey:keys){System.out.printf("Key: %s\n",Base64.getEncoder().encodeToString(key.getEncoded()));System.out.printf("Message: %s\n",message);Stringencrypted=encrypt(key,message);System.out.printf("Encrypted message: %s\n",encrypted);Stringdecrypted=decrypt(key,encrypted);System.out.printf("Decrypted message: %s\n",decrypted);System.out.println();}}}