feat: 암호화모듈 프레임워크 신규 구현
- CryptoModuleExtension 인터페이스: BC 프로바이더, AAD, 편의 메서드 오버로드 추가 - AESCryptoModuleExtension: CBC/GCM/ECB/FF1 지원, GCM 랜덤 nonce, AAD 처리 - ARIACryptoModuleExtension: ARIA 알고리즘 지원 - CryptoModuleConfigVO: JPA Entity 분리를 위한 Lombok VO - CryptoModuleManager: VO 패턴 적용, FQCN 기반 전략 동적 로딩(Class.forName) - CryptoModuleService: STATIC/DYNAMIC × AAD 조합 8가지 오버로드 - CryptoModuleConfigMapper: MapStruct Entity→VO 매퍼 - KeyDerivationStrategy 인터페이스 및 DerivedKey - HsmContextXorKeyDerivationStrategy: HSM 마스터키 XOR 컨텍스트값 전략 - ReloadCryptoModuleCommand: 설정 런타임 재로드 커맨드 - build.gradle: BouncyCastle bcprov-jdk15on:1.70 의존성 추가 - 단위 테스트 전체 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package com.eactive.eai.common.security;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.Key;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Security;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.bouncycastle.jcajce.spec.FPEParameterSpec;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
public class ARIACryptoModuleExtension implements CryptoModuleExtension {
|
||||
|
||||
private Cipher encryptEngine;
|
||||
private Cipher decryptEngine;
|
||||
|
||||
@Override
|
||||
public void init(String alg, String mode, String pad, byte[] encKey, byte[] decKey) throws Exception {
|
||||
this.init("ARIA", mode, pad, (byte[]) null, encKey, decKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(String alg, String mode, String pad, byte[] iv, byte[] encKey, byte[] decKey) throws Exception {
|
||||
if (Security.getProvider("BC") == null) {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
String m = mode != null ? mode : "";
|
||||
String p = pad != null ? pad : "";
|
||||
Key encKeySpec = new SecretKeySpec(encKey, "ARIA");
|
||||
Key decKeySpec = new SecretKeySpec(decKey, "ARIA");
|
||||
AlgorithmParameterSpec param = iv != null ? new IvParameterSpec(iv) : null;
|
||||
if (m.toLowerCase().contains("ff")) {
|
||||
param = new FPEParameterSpec(256, iv);
|
||||
}
|
||||
this.encryptEngine = Cipher.getInstance(String.format("ARIA/%s/%s", m, p));
|
||||
this.encryptEngine.init(Cipher.ENCRYPT_MODE, encKeySpec, param, (SecureRandom) null);
|
||||
this.decryptEngine = Cipher.getInstance(String.format("ARIA/%s/%s", m, p));
|
||||
this.decryptEngine.init(Cipher.DECRYPT_MODE, decKeySpec, param, (SecureRandom) null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encrypt(byte[] src, int sindex, int slength, byte[] dst, int dindex) throws Exception {
|
||||
return this.encryptEngine.doFinal(src, sindex, slength, dst, dindex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encrypt(byte[] src, int sindex, int slength) throws Exception {
|
||||
int size = (slength + 17) / this.encryptEngine.getBlockSize() * this.encryptEngine.getBlockSize();
|
||||
size += (slength + 17) % this.encryptEngine.getBlockSize() == 0 ? 0 : this.encryptEngine.getBlockSize();
|
||||
byte[] dst = new byte[this.encryptEngine.getOutputSize(size)];
|
||||
size = this.encrypt(src, sindex, slength, dst, 0);
|
||||
return ByteBuffer.allocate(size).put(dst, 0, size).array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int decrypt(byte[] src, int sindex, int slength, byte[] dst, int dindex) throws Exception {
|
||||
return this.decryptEngine.doFinal(src, sindex, slength, dst, dindex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] decrypt(byte[] src, int sindex, int slength) throws Exception {
|
||||
return this.decryptEngine.doFinal(src, sindex, slength);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user