ECDHESA256 암호화 추가

This commit is contained in:
jaewohong
2025-11-25 16:19:31 +09:00
parent b22c8601c0
commit ad5a5cbcfc
@@ -0,0 +1,112 @@
package com.kjbank.encrypt.exchange.crypto;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.*;
import com.nimbusds.jose.jwk.*;
import com.nimbusds.jose.jwk.gen.*;
import java.io.FileInputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.ECPublicKey;
import java.security.KeyStore;
import java.security.PrivateKey;
public class ECDHESA256Cipher {
private ECKey myECKey;
private ECKey receiverPublicJWK;
// 생성자: 수신자 키 쌍을 준비
public ECDHESA256Cipher() throws Exception {
this.myECKey = new ECKeyGenerator(Curve.P_256)
.keyUse(KeyUse.ENCRYPTION)
.keyID("receiver-key")
.generate();
this.receiverPublicJWK = myECKey.toPublicJWK();
}
//생성자: 내 키쌍 로드용 생성자 (복호화할 때 필요)
public ECDHESA256Cipher(String myKeystorePath, String storePass, String keyAlias, String keyPass) throws Exception {
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream(myKeystorePath), storePass.toCharArray());
PrivateKey myPrivateKey = (PrivateKey) ks.getKey(keyAlias, keyPass.toCharArray());
X509Certificate myCert = (X509Certificate) ks.getCertificate(keyAlias);
ECPublicKey myPublicKey = (ECPublicKey) myCert.getPublicKey();
this.myECKey = new ECKey.Builder(Curve.P_256, myPublicKey)
.privateKey(myPrivateKey)
.keyUse(KeyUse.ENCRYPTION)
//.keyID("my-key")
.keyID(myCert.getSerialNumber().toString()) // 인증서 시리얼번호를 keyID로 사용
.build();
}
// 생성자: 상대방 인증서에서 공개키 로드
public ECDHESA256Cipher(String certPath) throws Exception {
// 1. 인증서 로드
CertificateFactory cf = CertificateFactory.getInstance("X.509");
try (FileInputStream fis = new FileInputStream(certPath)) {
X509Certificate cert = (X509Certificate) cf.generateCertificate(fis);
// 2. 공개키 추출
ECPublicKey publicKey = (ECPublicKey) cert.getPublicKey();
// 3. Nimbus ECKey로 변환
this.receiverPublicJWK = new ECKey.Builder(Curve.P_256, publicKey)
.keyUse(KeyUse.ENCRYPTION)
//.keyID("receiver-key")
.keyID(cert.getSerialNumber().toString()) // 인증서 시리얼번호를 keyID로 사용
.build();
}
}
// 암호화 메서드
public String encrypt(String jsonPayload) throws Exception {
if (receiverPublicJWK == null) {
throw new IllegalStateException("상대방 공개키가 초기화되지 않았습니다.");
}
JWEHeader header = new JWEHeader.Builder(JWEAlgorithm.ECDH_ES_A256KW, EncryptionMethod.A256GCM)
.contentType("application/json")
.keyID(receiverPublicJWK.getKeyID())
.build();
JWEObject jweObject = new JWEObject(header, new Payload(jsonPayload));
JWEEncrypter encrypter = new ECDHEncrypter(receiverPublicJWK);
jweObject.encrypt(encrypter);
return jweObject.serialize();
}
// 복호화 메서드(상대방이 나한테 보낸것)
public String decrypt(String jweString) throws Exception {
if (myECKey == null) {
throw new IllegalStateException("내 개인키가 초기화되지 않았습니다.");
}
JWEObject decryptedJWE = JWEObject.parse(jweString);
JWEDecrypter decrypter = new ECDHDecrypter(myECKey);
decryptedJWE.decrypt(decrypter);
return decryptedJWE.getPayload().toString();
}
// 상대방 공개키를 외부에 제공할 수 있도록 getter
public ECKey getReceiverPublicJWK() {
if (receiverPublicJWK == null) {
throw new IllegalStateException("상대방 공개키가 초기화되지 않았습니다.");
}
return receiverPublicJWK;
}
// 내 공개키를 상대방에게 제공할 수 있도록 getter
public ECKey getMyPublicJWK() {
if (myECKey == null) {
throw new IllegalStateException("내 키쌍이 초기화되지 않았습니다.");
}
return myECKey.toPublicJWK();
}
}