Encode Base64 String text = "hello 世界" ;String encodeText = Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8));System.out.println(encodeText); String decodeText = new String (Base64.getDecoder().decode(encodeText), StandardCharsets.UTF_8);System.out.println(decodeText);
URL Encode String text = "hello 世界" ;String encodeText = URLEncoder.encode(text, StandardCharsets.UTF_8.name());System.out.println(encodeText); String decodeText = URLDecoder.decode(encodeText, StandardCharsets.UTF_8.name());System.out.println(decodeText);
Hash Algorithms MD5 MD5 (Message Digest 5)
String text = "123456" ;MessageDigest messageDigest = MessageDigest.getInstance("MD5" );messageDigest.reset(); messageDigest.update(text.getBytes(StandardCharsets.UTF_8)); byte [] digest = messageDigest.digest();String hashText = DatatypeConverter.printHexBinary(digest);System.out.println(hashText);
Note: the MessageDigest is not thread-safe . Consequently, we should use a new instance for every thread.
SHA SHA (Secure Hash Algorithm)
SHA-256 by MessageDigest
String text = "123456" ;MessageDigest messageDigest = MessageDigest.getInstance("SHA-256" );messageDigest.reset(); messageDigest.update(text.getBytes(StandardCharsets.UTF_8)); byte [] digest = messageDigest.digest();String hashText = DatatypeConverter.printHexBinary(digest);System.out.println(hashText);
SHA3-256 by MessageDigest (since Java 9)
String text = "123456" ;MessageDigest messageDigest = MessageDigest.getInstance("SHA3-256" );messageDigest.reset(); messageDigest.update(text.getBytes(StandardCharsets.UTF_8)); byte [] digest = messageDigest.digest();String hashText = DatatypeConverter.printHexBinary(digest);System.out.println(hashText);
Conclusion
SHA256 is difficult to handle than MD5 because of its size.
SHA256 is less secure than MD5
MD5 result in an output of 128 bits whereas SHA256 result output of 256 bits.
Concluding all points, it will be better to use MDA5 if you want to secure your files otherwise you can use SHA256.
Symmetric Encryption Algorithms DES DES (data encryption standard, 1976)
DES is Not Secure.
3DES 3DES is Not Secure.
AES AES (advanced encryption system, 2001)
The AES algorithm has six modes of operation:
ECB (Electronic Code Book) Not Recommend
CBC (Cipher Block Chaining)
CFB (Cipher FeedBack)
OFB (Output FeedBack)
CTR (Counter)
GCM (Galois/Counter Mode)
Don’t use AES Electronic codebook (ECB) Mode . The AES ECB mode, or AES/ECB/PKCS5Padding
(in Java) is not semantically secure .
AES encryption best practice : Don’t reuse IV with the same key.
IV
The IV (initial value or initial vector), it is random bytes, typically 12 bytes or 16 bytes. In Java, we can use SecureRandom
to generate the random IV.
public static IvParameterSpec generateIv () { byte [] iv = new byte [16 ]; new SecureRandom ().nextBytes(iv); return new IvParameterSpec (iv); }
secret key
The AES secret key, either AES-128
or AES-256
. In Java, we can use KeyGenerator
to generate the AES secret key.
public static SecretKey getAESKey () throws NoSuchAlgorithmException { KeyGenerator keyGen = KeyGenerator.getInstance("AES" ); keyGen.init(256 , SecureRandom.getInstanceStrong()); return keyGen.generateKey(); }
The AES secret key that derived from a given password. In Java, we can use the SecretKeyFactory
and PBKDF2WithHmacSHA256
to generate an AES key from a given password.
public static SecretKey getAESKeyFromPassword (char [] password, byte [] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256" ); KeySpec spec = new PBEKeySpec (password, salt, 65536 , 256 ); SecretKey secret = new SecretKeySpec (factory.generateSecret(spec).getEncoded(), "AES" ); return secret; }
salt
We use salt
to protect rainbow attacks, and it is also a random byte, we can use the SecureRandom to generate it.
import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.PBEKeySpec;import javax.crypto.spec.SecretKeySpec;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.security.spec.InvalidKeySpecException;import java.security.spec.KeySpec;import java.util.ArrayList;import java.util.List;public class CryptoUtils { public static byte [] getRandomNonce(int numBytes) { byte [] nonce = new byte [numBytes]; new SecureRandom ().nextBytes(nonce); return nonce; } public static SecretKey getAESKey (int keysize) throws NoSuchAlgorithmException { KeyGenerator keyGen = KeyGenerator.getInstance("AES" ); keyGen.init(keysize, SecureRandom.getInstanceStrong()); return keyGen.generateKey(); } public static SecretKey getAESKeyFromPassword (char [] password, byte [] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256" ); KeySpec spec = new PBEKeySpec (password, salt, 65536 , 256 ); SecretKey secret = new SecretKeySpec (factory.generateSecret(spec).getEncoded(), "AES" ); return secret; } public static String hex (byte [] bytes) { StringBuilder result = new StringBuilder (); for (byte b : bytes) { result.append(String.format("%02x" , b)); } return result.toString(); } public static String hexWithBlockSize (byte [] bytes, int blockSize) { String hex = hex(bytes); blockSize = blockSize * 2 ; List<String> result = new ArrayList <>(); int index = 0 ; while (index < hex.length()) { result.add(hex.substring(index, Math.min(index + blockSize, hex.length()))); index += blockSize; } return result.toString(); } }
CBC Mode
Input
algorithm: AES/CBC/PKCS5Padding
iv bytes
aes key bits
secretKey: generate by password
Initialization Vector (IV): random bytes
GCM Mode
Asymmetric Encryption Algorithms RSA RSA (Rivest-Shamir-Adleman)
public static void getKeyPair () throws NoSuchAlgorithmException { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA" ); kpg.initialize(2048 ); KeyPair keyPair = kpg.generateKeyPair(); Key pub = keyPair.getPublic(); Key pvt = keyPair.getPrivate(); System.out.println("public key" ); System.out.println(Base64.getEncoder().encodeToString(pub.getEncoded())); System.out.println("private key" ); System.out.println(Base64.getEncoder().encodeToString(pvt.getEncoded())); } public static String decrypt (String privateKeyBase64String, String cipherText) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { KeyFactory keyFactory = KeyFactory.getInstance("RSA" ); EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec (Base64.getDecoder().decode(privateKeyBase64String.getBytes())); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte [] bytes = cipher.doFinal(Base64.getDecoder().decode(cipherText)); return new String (bytes); } public static String encrypt (String publicKeyBase64String, String plainText) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { KeyFactory keyFactory = KeyFactory.getInstance("RSA" ); EncodedKeySpec pkcs8KeySpec = new X509EncodedKeySpec (Base64.getDecoder().decode(publicKeyBase64String.getBytes())); PublicKey publicKey = keyFactory.generatePublic(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte [] bytes = cipher.doFinal(plainText.getBytes()); return new String (Base64.getEncoder().encode(bytes)); }
ECC ECC (Elliptic Curve Cryptography)
References [1] Java AES encryption and decryption