- java library를 이용한 DKIM 서명 및 검증 기능 구현하기2023년 11월 12일
- 알쓸개잡
- 작성자
- 2023.11.12.:38
java에서는 Email의 DKIM 서명 및 검증 처리를 위한 몇 가지 라이브러리를 제공한다.
이번 포스팅에서는 Email DKIM 서명 및 검증 구현을 위한 다음 라이브러리를 사용하는 방법에 대해서 기록한다.
- apache james 프로젝트의 jdkim 라이브러리
- SimpleJavaMail dkim 라이브러리
Email DKIM에 대한 상세 스펙에 대한 내용은 아래 포스팅을 참고하기 바란다.
2023.11.08 - [ETC] - Email DKIM(DomainKeys Identified Mail) 메시지 서명 및 검증 프로세스
Email DKIM(DomainKeys Identified Mail) 메시지 서명 및 검증 프로세스
DomainKeys Identified Mail (이하 DKIM)은 공개키 암호화 및 키 서버 기술을 사용하는 이메일에 대한 도메인 수준 인증 프레임워크를 정의하여 MTA(메일 전송 에이전트) 또는 MUA(메일 사용자 에이전트)에
devel-repository.tistory.com
우선 Email DKIM 기능을 제공하기 위해서는 RSA 개인키/공개키가 필요하며 공개키는 DNS의 TXT 레코드에 등록이 되어야 한다.
테스트를 위해서 실제 DNS에 공개키를 등록하지는 않을 것이다. 공개키를 코드 내에서 가져오도록 하여 검증 테스트는 진행할 것이다.
apache james 의 jdkim 라이브러리는 서명 및 검증을 위한 코드를 제공한다.
SimpleJavaMail dkim 라이브러리는 서명을 위한 코드를 제공한다. 또한 DKIM-Signature 헤더를 붙여 메일을 전송할 수도 있다.
public / private key 생성
DKIM 기능 제공을 위한 환경 구성을 위해서는 기본적으로 공개키(검증)/개인키(서명)가 필요하다.
$> openssl genrsa -out rsa.private 1024
위 명령은 1024 비트의 PEM 형식의 PKCS1 개인키를 생성한다.
공개키는 다음과 같이 생성한다.
$> openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM
java security 패키지는 PKCS1을 지원하지 않기 때문에 java security를 사용하여 개인키를 로딩하기 위해서는 PKCS8로 변환이 필요하다. PKCS1 -> PKCS8 변환 명령은 다음과 같다.
$> openssl pkey -in rsa.private -out pkcs8.rsa.private
위 명령은 PKCS8 개인키를 pkcs8.rsa.private 파일에 저장한다.
key 파일 저장 경로 DKIM 서명 및 검증을 위한 샘플 코드 프로젝트의 key 파일 경로는 위와 같다.
pkcs8.rsa.private 파일은 PKCS8 개인키 파일이다.
rsa.private 파일은 PKCS1 개인키 파일이다.
PKCS1, PKCS8 둘 중 하나를 선택해서 사용하면 되겠다.
rsa.public 파일은 공개키 파일이다.
만약 PKCS1 개인키를 로딩하려면 BouncyCastle 라이브러리를 사용한다.
디펜던시는 다음과 같다.
<!-- PKCS1 private key를 로딩하기 위한 라이브러리 --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.69</version> </dependency>
우선 bouncycastle 디펜던시 추가가 필요하다. PKCS1 개인키를 로딩하는 코드는 다음과 같다.
//PKCS1 유형의 private key를 loading 하기 위해서 BouncyCastle 라이브러리 사용 //java는 PKCS1을 지원하지 않는다. //https://www.baeldung.com/java-read-pem-file-keys#2-read-private-key //혹은 PKCS1 -> PKCS8로 변환 후 public static RSAPrivateKey loadPrivateKeyPKCS1(Path keyPath) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException { Security.addProvider(new BouncyCastleProvider()); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); try (FileReader keyReader = new FileReader(keyPath.toFile()); PemReader pemReader = new PemReader(keyReader)) { PemObject pemObject = pemReader.readPemObject(); byte[] content = pemObject.getContent(); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(content); return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); } }
이번 포스팅에서 구현하는 샘플은 PKCS8 개인키를 사용한다.
샘플 Email
테스트를 위한 샘플 EML 파일 위치는 다음과 같다.
src/main/resources/sample.eml
라이브러리 dependency
apache james jdkim
<!-- apache james jdkim 라이브러리 --> <dependency> <groupId>org.apache.james.jdkim</groupId> <artifactId>apache-jdkim</artifactId> <version>0.3</version> </dependency>
simplejavamail dkim module
<!-- simplejavamail의 dkim 라이브러리 --> <dependency> <groupId>org.simplejavamail</groupId> <artifactId>utils-mail-dkim</artifactId> <version>3.0.0</version> </dependency>
Email 메시지 서명하기 (DKIM-Signature 헤더 생성하기)
샘플 코드에서 메시지 서명에 사용되는 필수 태그는 다음과 같다.
- a=rsa-sha256
- s=selector
- c=simple/simple
- d=test.com
- h=Content-Type:MIME-Version:Subject:Message-ID:To:Sender:From:Date
Key Loader 클래스
개인키 파일 로딩을 위해 사용되는 공통 클래스다.
package com.example.spring.dkim.common; import org.apache.james.jdkim.codec.binary.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.io.pem.PemObject; import org.bouncycastle.util.io.pem.PemReader; import java.io.FileReader; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.Security; import java.security.interfaces.RSAPrivateKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; public class RSAKeyLoader { //PKCS1 private key를 loading 하기 위해서 BouncyCastle 라이브러리 사용 //java는 PKCS1을 지원하지 않는다. //https://www.baeldung.com/java-read-pem-file-keys#2-read-private-key public static RSAPrivateKey loadPrivateKeyPKCS1(Path keyPath) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException { Security.addProvider(new BouncyCastleProvider()); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); try (FileReader keyReader = new FileReader(keyPath.toFile()); PemReader pemReader = new PemReader(keyReader)) { PemObject pemObject = pemReader.readPemObject(); byte[] content = pemObject.getContent(); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(content); return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); } } //PKCS8 private key를 loading public static RSAPrivateKey loadPrivateKeyPKCS8(Path keyPath) throws InvalidKeySpecException, NoSuchAlgorithmException, IOException { String privateKeyData = Files.readString(keyPath, Charset.defaultCharset()); String privateKeyPEM = privateKeyData .replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", ""); byte[] encoded = Base64.decodeBase64(privateKeyPEM); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); } }
apache james 라이브러리
다음은 apache james 라이브러리를 이용하여 DKIM-Signature를 생성하는 클래스다.
package com.example.spring.dkim.sign; import com.example.spring.dkim.common.RSAKeyLoader; import jakarta.mail.MessagingException; import lombok.extern.slf4j.Slf4j; import org.apache.james.jdkim.DKIMSigner; import org.apache.james.jdkim.exceptions.FailException; import org.springframework.core.io.ClassPathResource; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.spec.InvalidKeySpecException; @Slf4j public class JamesDKIMSign { public JamesDKIMSign() {} public void makeDkimSignMessage(Path originEml, Path outputEml) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, FailException, MessagingException { //DKIM-Signature header tag 셋팅 String signatureTemplate = "v=1; a=rsa-sha256; s=selector; c=simple/simple; d=test.com; " + "h=Content-Type:MIME-Version:Subject:Message-ID:To:Sender:From:Date; bh=; b="; //PKCS8 개인키를 로딩한다. ClassPathResource privateKeyResource = new ClassPathResource("keys/pkcs8.rsa.private"); PrivateKey privateKey = RSAKeyLoader.loadPrivateKeyPKCS8(privateKeyResource.getFile().toPath()); //PKCS1 개인키를 로딩하려면 아래 메서드를 호출한다. // ClassPathResource privateKeyResource = new ClassPathResource("keys/rsa.private"); // PrivateKey privateKey = RSAKeyLoader.loadPrivateKeyPKCS1(privateKeyResource.getFile().toPath()); DKIMSigner signer = new DKIMSigner(signatureTemplate, privateKey); String sign; try (InputStream inputStream = Files.newInputStream(originEml)) { //sign() 메서드 호출을 통해서 DKIM-Signature 헤더를 얻을 수 있다. //sign() 호출 이후 inputStream은 close 된다. sign = signer.sign(inputStream); log.info("{}", sign); sign += "\r\n"; } //outputEml 에 DKIM-Signature 헤더를 추가하여 originEml을 복사한다. try (InputStream inputStream = Files.newInputStream(originEml); OutputStream outputStream = Files.newOutputStream(outputEml)) { outputStream.write(sign.getBytes(Charset.defaultCharset())); outputStream.write(inputStream.readAllBytes()); } } }
//target/classes/sample.eml 파일에 대한 DKIM-Signature 헤더를 생성하여 //DKIM-Signature 헤더가 삽입된 target/classes/sample-james-dkim.eml 파일을 생성한다. Path jamesSign() { try { JamesDKIMSign jamesDKIMSign = new JamesDKIMSign(); ClassPathResource resource = new ClassPathResource("sample.eml"); Path originEmlPath = resource.getFile().toPath(); Path outputEmlPath = originEmlPath.resolveSibling("sample-james-dkim.eml"); jamesDKIMSign.makeDkimSignMessage(originEmlPath, outputEmlPath); return outputEmlPath; } catch (Exception e) { log.error("fail to dkim sign by james library, {}", e.getMessage()); return null; } }
- apache james 라이브러리의 경우 메시지 서명을 위해서는 우선 signatureTemplate를 미리 정의해야 한다.
- signatureTemplate에서 b=, bh= 태그는 모두 공백문자로 세팅해야 한다.
- PrivateKey 인스턴스를 전달해야 한다.
- PrivateKey 인스턴스는 src/main/resources/keys/pkcs8.rsa.private 파일로부터 생성된다.
위 코드에서 DKIMSigner.sign() 메서드를 호출하여 얻은 DKIM-Signature 헤더는 다음과 같다.
DKIM-Signature: a=rsa-sha256; b=W0kFoDrivKbcY3xWfMWg2Z2YogyFy7e/rilBh5CBMDZwbbi/jNKbnC/yvlgyceYexk0jVRIoB0N2BYVB3j9P4K07XOS79TKdEVvyjmckN8UdnVS7338EezB8t6v/O3bNVRzSt5YsJF1RZXTUE2LJfV/eBaIqlOoo7DetgtCXZqQ=; s=selector; c=simple/simple; d=test.com; v=1; bh=QUg010Sn3BHY0WzkYjKB6QDkD5XZxhSEsiPcC0PyX0E=; h=Content-Type:MIME-Version:Subject:Message-ID:To:Sender:From:Date;
하지만 다음과 같은 문제가 있다.
- james jdkim 라이브러리를 통해서 얻은 DKIM-Signature 헤더는 folding이 되지 않는다.
- Email 메시지 헤더의 한 라인 길이의 제한이 있기 때문에 이를 그대로 사용하기에는 무리가 있다.
SimpleJavaMail 라이브러리
다음은 SimpleJavaMail 라이브러리를 이용하여 DKIM-Signature를 생성하는 클래스다.
package com.example.spring.dkim.sign; import com.example.spring.dkim.common.RSAKeyLoader; import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeMessage; import org.simplejavamail.utils.mail.dkim.Canonicalization; import org.simplejavamail.utils.mail.dkim.DkimMessage; import org.simplejavamail.utils.mail.dkim.DkimSigner; import org.simplejavamail.utils.mail.dkim.SigningAlgorithm; import org.springframework.core.io.ClassPathResource; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPrivateKey; import java.security.spec.InvalidKeySpecException; public class SimpleJavaDKIMSign { /** * @param originEml DKIM 서명하고자 하는 EML 경로 * @param outputEml DKIM 서명 헤더를 붙인 새로운 EML 경로 */ public void makeDkimSignMessage(Path originEml, Path outputEml) throws IOException, MessagingException, InvalidKeySpecException, NoSuchAlgorithmException { try (InputStream inputStream = Files.newInputStream(originEml); OutputStream outputStream = Files.newOutputStream(outputEml)) { MimeMessage originMessage = new MimeMessage(null, inputStream); DkimMessage dkimMessage = getDkimMessage(originMessage); dkimMessage.writeTo(outputStream); } //check exists DKIM-Signature header try (InputStream inputStream = Files.newInputStream(outputEml)) { MimeMessage outputMessage = new MimeMessage(null, inputStream); String[] header = outputMessage.getHeader("DKIM-Signature"); assert header.length > 0; } } private DkimMessage getDkimMessage(MimeMessage message) throws InvalidKeySpecException, NoSuchAlgorithmException, IOException, MessagingException { final String domain = "test.com"; final String selector = "selector"; ClassPathResource privateKeyResource = new ClassPathResource("keys/pkcs8.rsa.private"); RSAPrivateKey privateKey = RSAKeyLoader.loadPrivateKeyPKCS8(privateKeyResource.getFile().toPath()); DkimSigner dkimSigner = new DkimSigner(domain, selector, privateKey); dkimSigner.setHeaderCanonicalization(Canonicalization.SIMPLE); dkimSigner.setBodyCanonicalization(Canonicalization.SIMPLE); dkimSigner.setSigningAlgorithm(SigningAlgorithm.SHA256_WITH_RSA); //지정된 도메인 및 지정된 selector에 대한 DNS 리소스 레코드가 올바르게 준비되었는지 확인하는 메서드다. //테스트를 위해서 실제로 DNS 구성을 하지 않았기 때문에 false로 지정한다. //리얼 환경에서는 아래 코드는 지정하지 않는 것이 좋다. dkimSigner.setCheckDomainKey(false); return new DkimMessage(message, dkimSigner); } }
//target/classes/sample.eml 파일에 대한 DKIM-Signature 헤더를 생성하여 //DKIM-Signature 헤더가 삽입된 target/classes/sample-simple-javamail-dkim.eml 파일을 생성한다. Path simpleJavaMailSign() { try { SimpleJavaDKIMSign simpleJavaDKIMSign = new SimpleJavaDKIMSign(); ClassPathResource resource = new ClassPathResource("sample.eml"); Path originEmlPath = resource.getFile().toPath(); Path outputEmlPath = originEmlPath.resolveSibling("sample-simple-javamail-dkim.eml"); simpleJavaDKIMSign.makeDkimSignMessage(originEmlPath, outputEmlPath); return outputEmlPath; } catch (Exception e) { log.error("fail to dkim sign by simple java mail library, {}", e.getMessage()); return null; } }
SimpleJavaMail 라이브러리를 사용하여 DKIM-Signature 헤더를 생성하는 이점은 다음과 같다.
- DKIM-Signature 헤더에 대한 folding이 자동 처리된다.
- 원문 EML에 대한 DKIM-Signature 헤더가 삽입된 새로운 EML을 생성하는 메서드를 제공한다. (DkimMessage.writeTo())
- signatureTemplate를 지정할 필요 없이 메서드를 통해 태그를 지정할 수 있다.
- 샘플코드에서는 비활성화 하였지만 공개키 조회를 위한 DNS 구성을 확인할 수 있는 메서드를 제공한다. (setCheckDomainKey(true))
생성된 DKIM-Signature 헤더는 다음과 같다.
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=simple/simple; t=1589272539; s=selector; d=test.com; h=Content-Type:MIME-Version:Subject:Message-ID:To:Sender:From:Date; bh=QUg010Sn3BHY0WzkYjKB6QDkD5XZxhSEsiPcC0PyX0E=; b=ZssTrtszInGe9heQjn5dSirqtjOOgcB80AgGpxa6Xzu8+7hyB+3St5Hw4Lfp7rtT kjXwalwuT+qK0Bi0Tvb6l5t6Y2NFtP8MDsFCjqHdDxdkz0N7b8NRA9hYBWZlwMSRk+J BNoOZNAiTv/yURjAucDxmgeyc6tz2+zNFGmdzhWo=
DKIM-Signature 헤더의 folding 처리가 잘 된 것을 확인할 수 있다.
DKIM 서명 검증하기 (DKIM-Signature 헤더 검증)
두개의 라이브러리 중에서 DKIM-Signature 헤더 검증 기능 제공은 apache james jdkim 라이브러리에서만 제공한다.
DKIMVerifier.verify() 메서드를 통해서 검증 기능을 제공하며 PublicKeyRecordRetriever 구현체를 생성자에 전달하지 않으면 기본적으로 DNSPublicKeyRecordRetriever 인스턴스가 사용되는데 DNSPublicKeyRecordRetriever 인스턴스는 DKIM-Signature 헤더의 s=(selector), d=(domain)을 기반으로 DNS에 등록된 공개키를 얻어와서 검증을 수행한다.
PublicKeyRecordRetriever 구현체 인스턴스를 생성자에 전달하면 공개키는 getRecords() 메서드를 통해서 얻어오게 된다.
PublicKeyRecordRetriever 인터페이스는 다음과 같다.
public interface PublicKeyRecordRetriever { /** * @param methodAndOption * the options declared for the lookup method. * @param selector * the value of "s=" tag * @param token * the value of the "d=" tag * @return A list of strings representing 0 to multiple records * @throws TempFailException * in case of timeout and other network errors. * @throws PermFailException * in case of unsupported options */ public List<String> getRecords(CharSequence methodAndOption, CharSequence selector, CharSequence token) throws TempFailException, PermFailException; }
메시지 서명 및 검증을 위한 테스트로써 실제 DNS에 공개키를 등록하지 않았기 때문에 PublicKeyRecordRetriever를 구현한 구현체를 직접 정의하여 getRecords() 메서드에 공개키를 하드코딩하여 리턴하도록 할 것이다.
다음 클래스는 공개키를 DNS 조회없이 리턴하도록 하는 클래스다.
package com.example.spring.dkim.verify; import org.apache.james.jdkim.api.PublicKeyRecordRetriever; import org.apache.james.jdkim.exceptions.PermFailException; import org.apache.james.jdkim.exceptions.TempFailException; import java.util.List; /** * PublicKeyRecordRetriever 클래스는 apache james의 jdkim 라이브러리에서 제공하는 인터페이스다. * 서명 검증시 내부적으로 DKIM-Signature 헤더의 selector, domain 정보를 기반으로 DNS 조회를 통해서 공개키를 가져오는데 * DNS 조회를 통해서 공개키를 가져오는 역할은 PublicKeyRecordRetriever 구현체가 담당한다. * 검증 테스트를 위해서 DNS에 공개키를 등록하지 않았기 때문에 하드코딩된 공개키를 가져오도록 한다. * PublicKeyRecordRetriever4Test 클래스는 하드코딩된 공개키 정보를 가져오도록 하기 위한 장치다. * p= 태그에 BEGIN PUBLIC KEY, END PUBLIC KEY 라인을 제외한 * resource/keys/rsa.public 파일의 공개키 내용을 직접 셋팅하도록 한다. */ public class PublicKeyRecordRetriever4Test implements PublicKeyRecordRetriever { @Override public List<String> getRecords( CharSequence methodAndOption, CharSequence selector, CharSequence token) { //example //String publicKeyRecord = "v=DKIM1; k=rsa; " + // "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjm1g0xmCM8eCveYP70SAdRNa1" + // "2y0absnxuOcZy/hvSyQqNqS5hoFcfvn/tQCO4LrcccLoRSueMOOc6l0rHpRcHluX++t" + // "FMbG7IkxcMT1Rk/vnBQ31GeTfeEbR4y/hBMdU5DDvRsvkSXXVlc9Us7m8te6hPFQYxtABCDEFGHIJKLMN"; String publicKeyRecord = "v=DKIM1; k=rsa; " + "p=<공개키데이터>"; return List.of(publicKeyRecord); } }
PublicKeyRecordRetriever4 Test는 공개키가 DNS에 등록되어 있지 않기 때문에 테스트를 위해서 정의한 클래스 이므로 리얼 환경에서는 정의해서 사용하면 안 된다.
리얼 환경에서는 DKIMVerifier 인스턴스 생성 시 디폴트 생성자를 통해서 인스턴스를 생성하도록 한다.다음은 DKIM-Signature 검증을 위한 클래스다.
package com.example.spring.dkim.verify; import lombok.extern.slf4j.Slf4j; import org.apache.james.jdkim.DKIMVerifier; import org.apache.james.jdkim.api.PublicKeyRecordRetriever; import org.apache.james.jdkim.api.SignatureRecord; import org.apache.james.jdkim.exceptions.FailException; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; @Slf4j public class JamesDKIMVerify { public JamesDKIMVerify() {} public void verify(Path emlPath) throws IOException, FailException { PublicKeyRecordRetriever publicKeyRecordRetriever = new PublicKeyRecordRetriever4Test(); try(InputStream inputStream = Files.newInputStream(emlPath)) { //리얼 환경에서는 publicKeyRecordRetriever 전달없이 디폴트 생성자를 호출한다. DKIMVerifier verifier = new DKIMVerifier(publicKeyRecordRetriever); List<SignatureRecord> verify = verifier.verify(inputStream); verify.forEach(signatureRecord -> log.info("signature record: {}", signatureRecord)); } } }
/** * apache james jdkim 라이브러리를 사용하여 파라미터로 전달된 경로의 EML 에 대한 DKIM 검증을 수행한다. * @param emlPath DKIM-Signature 헤더가 삽입된 eml 파일 경로 */ void verify(Path emlPath) { try { JamesDKIMVerify jamesDKIMVerify = new JamesDKIMVerify(); jamesDKIMVerify.verify(emlPath); } catch (Exception e) { log.error("fail to verify, {}", e.getMessage()); } }
지금까지 apache james jdkim 라이브러리와 SimpleJavaMail 라이브러리를 사용하여 Email DKIM 서명 및 검증을 위한 샘플 코드를 작성해 보았다.
결론
apache james jdkim을 사용하여 DKIM-Signature 헤더를 생성하면 몇 가지 문제가 있다.
- DKIM-Signature 헤더에 대해서 folding 처리가 되지 않기 때문에 헤더 라인 길이 제약에 문제가 생길 수 있다.
- 생성된 DKIM-Signature 헤더를 삽입한 EML을 생성할 수 있는 메서드를 제공하지 않아 이를 위해서는 직접 구현해야 한다.
- 미리 DKIM-Signature 헤더 템플릿을 정의해야 하며 사용함에 있어서 직관성이 떨어진다는 생각이 든다.
이에 반해 SimpleJavaMail 라이브러리를 사용하여 DKIM-Signature를 생성하면
- DKIM-Signature 헤더에 대한 folding 처리가 자동으로 수행된다.
- DKIM 공개키를 조회할 수 있는 DNS 구성이 제대로 되었는지 확인할 수 있는 기능을 제공한다.
- 생성된 DKIM-Signature 헤더를 삽입하여 새로운 EML 파일을 생성할 수 있도록 메서드를 제공한다.
- 사용에 있어서 조금 더 직관적이다.
- DKIM-Signature 헤더를 검증할 수 있는 기능을 제공하지 않는다.
DKIM 서명을 생성하는 코드는 SimpleJavaMail 라이브러리를 사용하고 검증을 위한 코드는 apache james jdkim 라이브러리를 사용하는 것이 좋을 듯하다.
전체 샘플 코드는 gitlab에서 확인할 수 있다.
https://gitlab.com/blog4031530/spring-dkim
참고링크
https://james.apache.org/jdkim/mailets/index.html
https://github.com/simple-java-mail/java-utils-mail-dkim
https://dkim.org/specs/rfc4871-dkimbase.html#creating-a-key
'ETC' 카테고리의 다른 글
맥 m1, m2 에 jmeter 사용하기 (0) 2023.12.02 맥 환경에서 iTerm2 개발 환경 셋팅하기 (0) 2023.12.01 Email DKIM(DomainKeys Identified Mail) 메시지 서명 및 검증 프로세스 (0) 2023.11.08 Email SPF (Sender Policy Framework) (0) 2023.10.28 테스트 환경을 위한 mariadb, kafka docker compose (0) 2023.09.18 다음글이전글이전 글이 없습니다.댓글