Google Code Prettify

2022年4月19日 星期二

Spring Security: AES 加解密

AES (Advanced Encryption Standard) 加密是美國聯邦政府採用的對稱式加密標準,用來取代原先使用多年的 DES (Data Encryption Standard) 加密。Spring Security 提供一個命名為 Encryptors 的類別,可以進行 AES 加解密,說明如下。

  • KeyGenerators

AES 加密需要 key 也需要 salt,這個工廠類別是密鑰產生器,產生出來的字串要當 key 或 salt 都可以,一般來說,key 會是人類取名,在必要時要求使用者需入,salt 則是系統產生,這個類別通常用來產生 salt。

如上圖,可以知道這個類別可以產生 BytesKeyGenerator 和 StringKeyGenerator 兩種密鑰產生器,BytesKeyGenerator 會產生 byte[] 的密鑰,StringKeyGenerator 則是 byte[] 的 hex 字串。

secureRandom 不帶參數時,產生的密鑰長度是 8 bytes,要指定長度就帶參數。

程式寫法如下:
String salt = KeyGenerators.string().generateKey();
  • Encryptors
產生加密類別的工廠類別,宣告如下:

這個工廠類別會產生兩種加密類別 -- BytesEncryptorTextEncryptor,這兩個類別都只有兩個 method - encrypt、descrypt,BytesEncryptor 的 method 傳入 byte[] 傳回 byte[],TextEncryptor 傳入 hex 值的字串,傳回 hex 值的字串。
@ExtendWith(SpringExtension.class)
@SpringBootTest
@Slf4j
class EncryptorsTest {
	private String salt = StringUtil.EMPTY;
	private String password = StringUtil.EMPTY;

	@BeforeEach
	void setUp() throws Exception {
		salt = KeyGenerators.string().generateKey();
		
		log.info("salt = " + salt);
		
		password = "P@ssw0rd";
	}

	@AfterEach
	void tearDown() throws Exception {
	}

	@Test
	void testBytesEncryptor() {
		
		BytesEncryptor encryptor = Encryptors.standard(password, salt);
		
		byte[] text = "習近平快GG了!".getBytes();
		
		byte[] encrypted = encryptor.encrypt(text);
		log.info(NumberUtil.toHex(encrypted));
		
		byte[] decrypted = encryptor.decrypt(encrypted);
		log.info(new String(decrypted));
	}
	
	@Test
	void testTextEncryptor() {
		TextEncryptor encryptor = Encryptors.text(password, salt);
		String encrypted = encryptor.encrypt("習近平快GG了!");
		log.info(encrypted);
		
		String decrypted = encryptor.decrypt(encrypted);
		log.info(decrypted);
	}
	
	@Test
	void testTextEncryptorAndBytesEncryptor() throws Exception {
		TextEncryptor textEncryptor = Encryptors.text(password, salt);
		String encrypted = textEncryptor.encrypt("習近平快GG了!");
		log.info(encrypted);
		
		BytesEncryptor bytesEncryptor = Encryptors.standard(password, salt);
		byte[] b = NumberUtil.hexToByte(encrypted);
		
		byte[] decryptedBytes = bytesEncryptor.decrypt(b);
		log.info(new String(decryptedBytes));
	}
}
如上,在 setUp()中產生 salt 及設定 password。testBytesEncryptor() 是測試 BytesEncryptor 的加解密,testTextEncryptor() 是測試 TextEncryptor 的加解密,testTextEncryptorAndBytesEncryptor() 則是驗證 TextEncryptor 產生的加密字串確實只是 hex 表示的字串。