본문으로 건너뛰기

Java 통합

sslTrus는 sslTrusJarsigner Java Provider를 제공하며, JDK에 포함된 jarsigner 도구와 함께 사용하여 원격 코드 서명 서비스를 통해 Java JAR 파일 서명을 완료할 수 있습니다.

서명 과정에서 코드 서명 개인 키는 항상 클라우드 HSM에 보관됩니다. 로컬에서는 서명할 데이터와 서명 구조를 생성하고, sslTrusJarsigner Provider를 통해 원격 서비스를 호출하여 개인 키 서명을 완료합니다.

JAR 서명 외에도 sslTrusJarsigner는 XMLDSig 서명 기능을 제공하여 XML 디지털 서명 시나리오에 사용할 수 있습니다.

준비 사항

사용 전에 다음을 준비하십시오.

  • JDK 8 이상 버전.
  • sslTrusJarsigner-<version>.jar.
  • Access Key.
  • Access Secret.
  • 인증서 번호(Cert Code).
  • 서명할 JAR 파일 또는 XML 파일.

본 문서의 예시에 나오는 <version>, 액세스 자격 증명, 인증서 번호 및 파일 경로는 모두 실제 값으로 대체해야 합니다.

sslTrusJarsigner 다운로드

sslTrusJarsigner 릴리스 페이지에서 최신 릴리스 패키지를 다운로드하고 압축을 해제합니다.

릴리스 패키지에는 다음이 포함됩니다.

sslTrusJarsigner-<version>.jar
SHA-256 校验文件

사용 전 SHA-256 체크섬으로 sslTrusJarsigner-<version>.jar 파일의 무결성을 검증하는 것을 권장합니다.

실행 환경 확인

먼저 Java와 JDK에 포함된 jarsigner가 정상적으로 사용 가능한지 확인합니다:

java -version
jarsigner -help

sslTrusJarsigner 버전 확인:

java -jar sslTrusJarsigner-<version>.jar --version

도움말 보기:

java -jar sslTrusJarsigner-<version>.jar --help

jarsigner 명령이 존재하지 않으면 현재 설치된 것이 Java Runtime만 포함된 실행 환경이 아닌 전체 JDK인지 확인하십시오.

액세스 자격 증명 구성

sslTrusJarsigner는 환경 변수를 통해 원격 코드 서명 서비스의 액세스 자격 증명과 인증서 번호를 읽습니다.

Linux 및 macOS

export SSLTRUS_JARSIGNER_ACCESS_KEY="YOUR_ACCESS_KEY"
export SSLTRUS_JARSIGNER_ACCESS_SECRET="YOUR_ACCESS_SECRET"
export SSLTRUS_JARSIGNER_CERT_CODE="YOUR_CERT_CODE"

Windows PowerShell

$env:SSLTRUS_JARSIGNER_ACCESS_KEY = "YOUR_ACCESS_KEY"
$env:SSLTRUS_JARSIGNER_ACCESS_SECRET = "YOUR_ACCESS_SECRET"
$env:SSLTRUS_JARSIGNER_CERT_CODE = "YOUR_CERT_CODE"

서비스 담당자가 전용 서비스 주소를 제공한 경우에는 SSLTRUS_JARSIGNER_URL도 설정해야 합니다.

Linux 및 macOS:

export SSLTRUS_JARSIGNER_URL="YOUR_SERVICE_URL"

Windows PowerShell:

$env:SSLTRUS_JARSIGNER_URL = "YOUR_SERVICE_URL"

전용 서비스 주소가 제공되지 않은 경우 이 변수를 설정할 필요가 없습니다.

Access Secret은 민감한 자격 증명이므로 소스 코드, 공개 설정 파일 또는 빌드 로그에 기록해서는 안 됩니다. 자동화 환경에서는 CI/CD Secret 또는 기타 자격 증명 관리 메커니즘을 통해 주입하는 것을 권장합니다.

JAR 서명

sslTrusJarsigner는 Java Security Provider 메커니즘을 통해 표준 jarsigner 도구와 통합됩니다.

아래 예제는 다음을 수행합니다:

app-unsigned.jar

서명 후 출력 결과:

app-signed.jar

JDK 9 이상 버전

Linux 및 macOS:

jarsigner \
-keystore NONE \
-storetype SSLTRUS \
-storepass SSLTRUS \
-providerPath "sslTrusJarsigner-<version>.jar" \
-providerClass com.racent.codesign.SSLTrusProvider \
-sigalg SHA256withRSA \
-tsa http://timestamp.sectigo.com \
-signedjar "app-signed.jar" \
"app-unsigned.jar" \
"$SSLTRUS_JARSIGNER_CERT_CODE"

Windows PowerShell:

jarsigner `
-keystore NONE `
-storetype SSLTRUS `
-storepass SSLTRUS `
-providerPath "sslTrusJarsigner-<version>.jar" `
-providerClass com.racent.codesign.SSLTrusProvider `
-sigalg SHA256withRSA `
-tsa http://timestamp.sectigo.com `
-signedjar "app-signed.jar" `
"app-unsigned.jar" `
"$env:SSLTRUS_JARSIGNER_CERT_CODE"

JDK 8

JDK 8에서 Provider를 로드하는 방식은 JDK 9 이상 버전과 다릅니다.

먼저 확인합니다:

JAVA_HOME

전체 JDK 8 설치 디렉터리를 가리킵니다.

Linux 및 macOS:

jarsigner \
-J-cp \
-J"$JAVA_HOME/lib/tools.jar:sslTrusJarsigner-<version>.jar" \
-keystore NONE \
-storetype SSLTRUS \
-storepass SSLTRUS \
-providerClass com.racent.codesign.SSLTrusProvider \
-sigalg SHA256withRSA \
-tsa http://timestamp.sectigo.com \
-signedjar "app-signed.jar" \
"app-unsigned.jar" \
"$SSLTRUS_JARSIGNER_CERT_CODE"

Windows PowerShell:

jarsigner `
-J-cp `
"-J$env:JAVA_HOME\lib\tools.jar;sslTrusJarsigner-<version>.jar" `
-keystore NONE `
-storetype SSLTRUS `
-storepass SSLTRUS `
-providerClass com.racent.codesign.SSLTrusProvider `
-sigalg SHA256withRSA `
-tsa http://timestamp.sectigo.com `
-signedjar "app-signed.jar" `
"app-unsigned.jar" `
"$env:SSLTRUS_JARSIGNER_CERT_CODE"

使用时需要注意:

  • 명령어 마지막의 인증서 번호는 SSLTRUS_JARSIGNER_CERT_CODE와 일치해야 합니다.
  • 원본 JAR을 덮어쓰지 않도록 -signedjar를 사용하여 새 파일로 출력하는 것을 권장합니다.
  • 예시에서는 SHA256withRSA를 사용하여 코드 서명을 완료합니다.
  • 타임스탬프가 필요하지 않은 경우 -tsa 및 그 뒤의 타임스탬프 주소를 삭제할 수 있습니다.

타임스탬프

정식으로 배포하는 JAR 서명에는 신뢰할 수 있는 타임스탬프를 추가하는 것을 권장합니다.

예시에서 사용:

http://timestamp.sectigo.com

해당 매개변수:

-tsa http://timestamp.sectigo.com

타임스탬프는 서명이 발생한 시간을 증명하는 데 사용되며, 원본 JAR 파일을 타임스탬프 서버에 업로드하지 않습니다.

다른 타임스탬프 서비스를 사용해야 하는 경우, -tsa 뒤의 주소를 실제 서명 정책에 부합하는 TSA 주소로 교체할 수 있습니다.

다양한 타임스탬프 서비스 및 프로덕션 환경 선택에 관해서는 참고 자료를 참조하십시오.

XML 서명

sslTrusJarsigner는 XML 디지털 서명 기능도 제공합니다.

XML 파일은 sign-xml 명령을 통해 XMLDSig Enveloped Signature를 생성할 수 있습니다.

서명 과정에서 로컬은 XMLDSig에 필요한 다이제스트와 서명 구조 생성을 담당하며, 실제 RSA 개인 키 서명은 원격 코드 서명 서비스에 의해 완료됩니다.

Linux 및 macOS

java -jar sslTrusJarsigner-<version>.jar \
sign-xml \
"input.xml" \
"signed.xml" \
"$SSLTRUS_JARSIGNER_CERT_CODE"

Windows PowerShell

java -jar sslTrusJarsigner-<version>.jar `
sign-xml `
"input.xml" `
"signed.xml" `
"$env:SSLTRUS_JARSIGNER_CERT_CODE"

기본 출력되는 KeyInfo 에는 리프 인증서만 포함됩니다. 수신자가 XML에 전체 인증서 체인을 포함하도록 요구하는 경우, 명령 끝에 --full-chain 매개변수를 추가할 수 있습니다.

실행 완료 후:

input.xml

원본 XML 파일의 경우,

signed.xml

XML 디지털 서명이 포함된 출력 파일의 경우.

코드 서명 개인 키는 XML 파일에 기록되지 않으며 로컬 컴퓨터에도 저장되지 않습니다.

검증 파일 생성

서명이 완료되면 서명 검증에 사용할 JKS 파일을 생성할 수 있습니다.

Linux 및 macOS:

java -jar sslTrusJarsigner-<version>.jar \
generate-keystore \
"$SSLTRUS_JARSIGNER_CERT_CODE" \
"verify.jks" \
"SSLTRUS"

Windows PowerShell:

java -jar sslTrusJarsigner-<version>.jar `
generate-keystore `
"$env:SSLTRUS_JARSIGNER_CERT_CODE" `
"verify.jks" `
"SSLTRUS"

생성:

verify.jks

该 파일은 서명 검증 전용이며, 코드 서명 실행에는 사용할 수 없습니다.

코드 서명 개인 키는 여전히 원격 HSM에 저장되며, verify.jks에 기록되지 않습니다.

JAR 서명 검증

생성된 verify.jks를 사용하여 서명을 검증합니다.

jarsigner \
-verify \
-verbose \
-certs \
-keystore "verify.jks" \
-storetype JKS \
-storepass "SSLTRUS" \
"app-signed.jar"

JAR에 이미 포함된 서명 정보만 확인하려면 다음을 실행하세요.

jarsigner -verify -verbose -certs "app-signed.jar"

서명 검증은 기존 서명만 확인하며, 원격 개인 키를 다시 호출하여 서명을 수행하지 않습니다.

서명 횟수

Jarsigner의 서명 횟수는 실제로 성공적으로 완료된 원격 서명 작업을 기준으로 계산됩니다.

일반적으로:

작업서명 횟수
JAR 하나에 성공적으로 서명 1회1회
JAR 3개를 각각 서명3회
동일한 JAR에 대해 서명을 한 번 더 실행1회 추가
jarsigner -verify 서명 검증0회
verify.jks 생성0회

따라서 서명 횟수는 Java 프로젝트의 소스 코드 파일 수가 아니라, 실제로 성공한 서명 작업이 몇 번 수행되었는지에 따라 달라집니다.

자세한 규칙은 참고 자료를 참조하십시오.

자주 묻는 질문

Access Key, Access Secret 또는 인증서 번호 누락

현재 터미널에 설정되어 있는지 확인하십시오:

SSLTRUS_JARSIGNER_ACCESS_KEY
SSLTRUS_JARSIGNER_ACCESS_SECRET
SSLTRUS_JARSIGNER_CERT_CODE

환경 변수를 설정한 후에는 동일한 터미널 세션에서 서명 명령을 실행해야 합니다.

Invalid option: -providerPath

다음과 같은 메시지가 나타나면:

Invalid option: -providerPath

일반적으로 현재 JDK 8을 사용하고 있음을 나타냅니다.

JDK 8은 JDK 9 이상 버전 예시의 -providerPath 매개변수를 사용하지 않으므로, 본 문서에서 제공하는 JDK 8 명령어를 사용하시기 바랍니다.

SSLTrusProvider를 로드할 수 없음

로드할 수 없다는 메시지가 표시되는 경우:

com.racent.codesign.SSLTrusProvider

다음을 확인하십시오:

  • sslTrusJarsigner-<version>.jar 경로가 올바른지 확인하십시오.
  • 파일 이름의 버전 번호가 실제 파일과 일치하는지 확인하십시오.
  • JDK 8 환경에서 JAVA_HOME가 완전한 JDK를 가리키는지 확인하십시오.

인증서 또는 alias를 찾을 수 없음

다음을 확인하십시오:

  • 인증서 번호가 올바른지 확인하십시오.
  • 명령 마지막에 지정한 인증서 번호가 SSLTRUS_JARSIGNER_CERT_CODE와 일치하는지 확인하십시오.
  • 현재 Access Key와 Access Secret에 해당 인증서의 사용 권한이 있는지 확인하십시오.

원격 서명 요청 실패

다음을 확인하십시오:

  • 현재 네트워크에서 원격 코드 서명 서비스에 접근할 수 있는지 확인하십시오.
  • 프록시, 방화벽 및 DNS 구성이 정상적인지 확인하십시오.
  • Access Key와 Access Secret이 올바른지 확인하십시오.
  • 인증서 번호가 올바른지 확인하십시오.
  • 전용 서비스 주소를 사용하는 경우 SSLTRUS_JARSIGNER_URL가 실제 제공 정보에 따라 구성되었는지 확인하십시오.

문제를 진단할 때 전체 오류 정보를 보존할 수 있지만, 로그나 오류 스크린샷을 제출하기 전에 Access Secret 등 민감한 자격 증명을 삭제하거나 마스킹해야 합니다.

타임스탬프 실패

현재 네트워크에서 -tsa가 지정한 타임스탬프 서버에 접근할 수 있는지 확인하십시오.

업무상 허용된다면 일시적으로 제거할 수 있습니다:

-tsa <URL>

서명을 다시 실행하여 문제가 원격 코드 서명 단계에서 발생했는지, 타임스탬프 요청 단계에서 발생했는지 확인합니다.

보안 안내

Java 통합 과정에서 다음 사항에 주의해야 합니다.

  • Access Secret은 민감한 자격 증명으로 보관해야 합니다.
  • 액세스 자격 증명을 Git 저장소에 커밋하지 마세요.
  • 로그에 전체 Access Secret을 출력하지 마세요.
  • verify.jks는 검증 전용이며 원격 서명에 사용할 수 있는 개인 키가 포함되어 있지 않습니다.
  • 로컬 sslTrusJarsigner Provider는 코드 서명 개인 키를 저장하지 않습니다.
  • 개인 키 서명 작업은 항상 원격 코드 서명 서비스에서 수행됩니다.
  • 자동화 환경에서는 CI/CD Secret 또는 전용 자격 증명 관리 시스템을 사용하여 액세스 자격 증명을 주입하는 것이 좋습니다.

관련 통합 방식

Java JAR 또는 XML 파일이 아닌 파일에 서명해야 하는 경우 실제 시나리오에 따라 다른 통합 방식을 선택할 수 있습니다.

시나리오통합 방식
명령줄에서 EXE, DLL, MSI 등 파일에 직접 서명클라이언트 도구
Microsoft SignTool, Visual Studio 등 Windows 도구Windows Provider
GitHub Actions, Electron Builder 등 자동화 빌드CI/CD 및 빌드 도구
원격 서명 클라이언트를 직접 개발API 통합