id-aes128-GCM 加解密example
id-aes128-GCM 比较好的地方是可以选用NoPadding。
The Galois/Counter Mode (GCM) is specified in [GCM]. GCM is a generic authenticated encryption block cipher mode. GCM is defined for use with any 128-bit block cipher, but in this document, GCM is used with the AES block cipher. AES-GCM has four inputs: an AES key, an initialization vector (IV), a plaintext content, and optional additional authenticated data (AAD). AES-GCM generates two outputs: a ciphertext and message authentication code (also called an authentication tag). To have a common set of terms for AES-CCM and AES-GCM, the AES-GCM IV is referred to as a nonce in the remainder of this document. The nonce is generated by the party performing the authenticated encryption operation. Within the scope of any authenticated- encryption key, the nonce value MUST be unique. That is, the set of nonce values used with any given key MUST NOT contain any duplicate values. Using the same nonce for two different messages encrypted with the same key destroys the security properties. AAD is authenticated but not encrypted. Thus, the AAD is not included in the AES-GCM output. It can be used to authenticate plaintext packet headers. In the CMS authenticated-enveloped-data content type, authenticated attributes comprise the AAD.
示例代码如下:
1 import org.apache.commons.codec.binary.Hex; 2 import org.bouncycastle.jce.provider.BouncyCastleProvider; 3 4 import java.nio.ByteBuffer; 5 import java.nio.charset.StandardCharsets; 6 import java.security.*; 7 8 import javax.crypto.*; 9 10 import lombok.extern.slf4j.Slf4j; 11 12 13 @Slf4j 14 public class AESGCMExample { 15 16 private static final byte[] SECRET_KEY_BYTE = {88, -91, -8, -75, 63, -16, 16, -90, 46, -78, -23, -125, 3, -9, -46, -48}; 17 private static final SecretKey SECRET_KEY = new SecretKeySpec(SECRET_KEY_BYTE, "AES"); 18 19 private static final byte[] OFFSET_IV = {-120, -77, 95, -88, -73, 88, 121, 119, 119, -37, -81, -88, 29, -13, -68, -97}; 20 21 private static final String CIPHER_TYPE = "AES/GCM/NoPadding"; 22 23 static { 24 Security.addProvider(new BouncyCastleProvider()); 25 } 26 27 public static byte[] encrypt(String data) { 28 try { 29 Cipher cipher = Cipher.getInstance(CIPHER_TYPE); 30 31 AlgorithmParameterSpec parameterSpec = new GCMParameterSpec(128, OFFSET_IV); //128 bit auth tag length 32 cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY, parameterSpec); 33 34 byte[] cipherText = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)); 35 ByteBuffer byteBuffer = ByteBuffer.allocate(OFFSET_IV.length + cipherText.length); 36 byteBuffer.put(OFFSET_IV); 37 byteBuffer.put(cipherText); 38 return byteBuffer.array(); 39 } catch (NoSuchAlgorithmException 40 | NoSuchPaddingException 41 | InvalidKeyException 42 | InvalidAlgorithmParameterException 43 | IllegalBlockSizeException 44 | BadPaddingException e) { 45 log.error("AES failed to encrypt", e); 46 } 47 return null; 48 } 49 50 public static String decrypt(byte[] cipherMessage) { 51 try { 52 final Cipher cipher = Cipher.getInstance(CIPHER_TYPE); 53 AlgorithmParameterSpec gcmIv = new GCMParameterSpec(128, cipherMessage, 0, OFFSET_IV.length); 54 cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY, gcmIv); 55 byte[] plainText = cipher.doFinal(cipherMessage, OFFSET_IV.length, cipherMessage.length - OFFSET_IV.length); 56 return new String(plainText, StandardCharsets.UTF_8); 57 } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | 58 InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) { 59 log.error("AES failed to decrypt", e); 60 } 61 return null; 62 } 63 64 public static void main(String args[]) throws Exception { 65 String originPlainText = "{\"Hello\": \"World\"}"; 66 byte[] cipherText = encrypt(originData); 67 System.out.println(Hex.encodeHexString(cipherText)); 68 String plainText = decrypt(cipherText); 69 System.out.println(plainText); 70 } 71 72 }