Java에서 문서에 디지털 서명 추가하는 방법
소개
디지털 서명 추가 기능(add digital signature java)을 구현하는 것은 마인필드를 헤매는 느낌일 수 있습니다. 인증서 형식, 서명 위치, 엄격한 보안 정책을 모두 다루어야 하며, 사용자 경험을 원활하게 유지해야 합니다. 한 번의 실수로 잘못된 서명이나 Adobe Reader에서 검증에 실패하는 문서가 생길 수 있습니다.
다행히도, 휠을 다시 만들거나 저수준 암호화와 씨름할 필요는 없습니다. 계약 관리 포털, 서명된 영수증이 필요한 전자상거래 결제, 혹은 내부 HR 워크플로우를 구축하든, 신뢰할 수 있는 Java 라이브러리는 개발 시간을 몇 시간 절감하고 일반적인 함정을 없애줍니다.
이 가이드에서는 디지털 서명의 복잡한 작업을 추상화한 상용 라이브러리 GroupDocs.Signature for Java를 살펴보겠습니다. 다음을 배울 수 있습니다:
- 라이브러리를 설정하고 인증서를 올바르게 구성하기
- PDF, Word, Excel, PowerPoint 파일에 전문적인 시각 스탬프를 사용해 서명하기
- 서명을 검증하고 신뢰할 수 없는 인증서나 메모리 병목 현상과 같은 일반 오류 처리하기
- 운영 환경을 위한 모범 보안 조치를 적용하기
마지막까지 진행하면, 애플리케이션이 처리하는 모든 문서 유형에 확장할 수 있는 즉시 사용 가능한 구현을 얻게 됩니다.
빠른 답변
- Java에서 디지털 서명을 추가할 수 있는 라이브러리는 무엇인가요? GroupDocs.Signature for Java.
- 지원되는 문서 형식은 몇 개입니까? PDF, DOCX, XLSX, PPTX 및 이미지 파일을 포함해 30개 이상.
- 운영 환경에 라이선스가 필요합니까? 예—상용 라이선스를 사용하면 워터마크가 제거되고 전체 기능을 사용할 수 있습니다.
- 대용량 PDF(100페이지 이상)를 OOM 오류 없이 서명할 수 있나요? 예—JVM 힙을 조정하고
setAllPages(false)옵션을 사용하면 됩니다. - 타임스탬프가 지원되나요? 물론입니다; 장기 유효성을 위해 신뢰할 수 있는 타임스탬프 인증기관(TSA) 토큰을 첨부할 수 있습니다.
add digital signature java란 무엇인가요?
add digital signature java는 Java API를 사용해 디지털 문서에 암호화 서명을 삽입하는 프로그래밍 과정을 의미합니다. 서명은 디지털 인증서로 검증된 서명자의 신원을 문서 내용에 결합하여 무결성, 부인 방지 및 플랫폼 간 법적 효력을 보장합니다.
Java에서 디지털 서명을 구현해야 하는 이유
GroupDocs.Signature는 30개 이상의 입력 및 출력 형식을 지원하며 전체 파일을 메모리에 로드하지 않고 500 MB까지 처리할 수 있어 수동 PDFBox 구현에 비해 2‑5배 빠른 속도를 제공합니다. 이러한 정량적인 이점은 고용량 작업에서 거래 시간을 단축하고 서버 비용을 절감합니다.
사전 요구 사항
시작하기 전에 다음이 준비되어 있는지 확인하십시오:
Java Development Kit (JDK) 8+ – JDK 11은 향상된 TLS 지원으로 권장됩니다.
IDE – IntelliJ IDEA, Eclipse, 또는 Java 확장이 포함된 VS Code.
GroupDocs.Signature for Java – 빌드에 추가하는 세 가지 방법을 보여드립니다.
유효한 디지털 인증서 (PFX 또는 P12 형식) – 개인 키와 비밀번호가 필요합니다.
Maven 또는 Gradle에 대한 친숙함 – 의존성 관리를 위해.
서명 흐름을 테스트할 샘플 PDF, DOCX 또는 XLSX 파일.
GroupDocs.Signature for Java를 어떻게 설치하나요?
GroupDocs.Signature는 빌드 구성에 간단히 추가하면 됩니다. 사용 중인 빌드 도구에 맞는 스니펫을 사용하고, 자리표시자 버전을 최신 안정 버전으로 교체한 뒤 Maven Central에서 라이브러리를 가져오기 위해 빌드 명령을 실행하십시오.
Maven (pom.xml에 추가):
<dependency>
<groupId>com.groupdocs</groupId>
<artifactId>groupdocs-signature</artifactId>
<version>23.12</version>
</dependency>
Gradle (build.gradle에 추가):
implementation 'com.groupdocs:groupdocs-signature:23.12'
수동 설치 (빌드 도구를 사용하지 않을 경우):
공식 릴리스 페이지 — GroupDocs.Signature for Java releases — 에서 JAR를 다운로드하고 클래스패스에 추가하십시오.
전문가 팁: 항상 최신 안정 버전을 참조하십시오. 현재 작성 시점에서는 버전 23.12가 최신이며, 이후 릴리스에는 보안 패치와 성능 개선이 포함되는 경우가 많습니다.
GroupDocs 라이선스를 어떻게 얻고 적용하나요?
GroupDocs.Signature는 운영 환경 사용을 위해 라이선스가 필요합니다. 라이선스를 적용하면 워터마크가 제거되고 전체 기능을 사용할 수 있어 서명된 문서가 기업 정책을 준수하도록 보장합니다.
- 무료 체험: Temporary License Page에서 30일 임시 라이선스를 받으세요.
- 유료 라이선스: GroupDocs Purchase Page에서 개발자 또는 엔터프라이즈 라이선스를 구매하십시오.
유효한 라이선스가 없으면 서명된 문서에 눈에 보이는 워터마크가 삽입되며, 이는 평가용으로만 유용합니다.
Signature 객체를 어떻게 초기화하나요?
Signature 클래스는 모든 문서 작업의 진입점입니다. 메모리 내에서 단일 파일을 나타내며 서명, 검증 및 서명 추출 메서드를 제공합니다. Signature 인스턴스를 생성하면 대상 파일을 로드하고 추가 처리를 위해 준비합니다.
Signature signature = new Signature("path/to/input.pdf");
무슨 일이 일어나고 있나요?
해당 라인은 대상 문서를 로드하는 Signature 인스턴스를 생성합니다. 경로는 절대 또는 상대 경로일 수 있으며, 파일이 존재하는지 확인하십시오. 이 객체는 여러 서명 또는 검증 작업에 재사용할 수 있어 배치 시 오버헤드를 줄입니다.
디지털 서명 옵션을 어떻게 구성하나요?
디지털 서명 옵션은 인증서 정보, 시각적 외관, 배치 규칙 등 유효한 PKI 서명을 만들기 위해 필요한 모든 설정을 포함합니다. 올바른 구성을 통해 생성된 서명이 암호학적으로 견고하고 문서 유형에 맞는 시각적 형태를 갖추게 됩니다.
인증서 세부 정보를 어떻게 설정하나요?
DigitalSignOptions 클래스는 모든 인증서 관련 설정을 보관합니다. 아래는 이 클래스에 대한 최초 정의 앵커입니다.
DigitalSignOptions는 라이브러리가 유효한 PKI 서명을 만들 때 사용하는 인증서 파일, 비밀번호 및 선택적 메타데이터와 같은 암호화 매개변수를 정의합니다.
DigitalSignOptions options = new DigitalSignOptions();
options.setCertificatePath("YOUR_DOCUMENT_DIRECTORY/certificate.pfx");
options.setCertificatePassword("yourPassword");
options.setReason("Approved Contract");
options.setContact("legal@yourcompany.com");
options.setLocation("New York, USA");
핵심 포인트:
- 비밀번호를 절대 하드코딩하지 말고 환경 변수나 비밀 관리자를 통해 로드하십시오.
- 검토자가 서명 속성을 확인할 때
setReason,setContact,setLocation을 사용해 컨텍스트를 제공하십시오.
서명의 시각적 외관을 어떻게 맞춤화하나요?
SignatureOptions(DigitalSignOptions의 서브클래스)는 페이지 내 렌더링을 제어합니다. 이미지 첨부, 크기 조정, 페이지 내 시각적 스탬프 위치 지정이 가능합니다.
SignatureOptions는 이미지 첨부, 크기 조정, 페이지 내 시각적 스탬프 위치 지정이 가능합니다.
options.setImageFilePath("YOUR_DOCUMENT_DIRECTORY/signature.png");
options.setAllPages(true);
options.setWidth(150);
options.setHeight(0); // Auto‑scale based on image aspect ratio
- ImageFilePath: 손글씨 서명 또는 기업 로고의 PNG 또는 JPG 파일 경로를 지정합니다. 투명 PNG가 가장 좋습니다.
- AllPages: 모든 페이지에 증명이 필요하면
true로 설정하고, 그렇지 않으면false로 설정하면 마지막 페이지만 서명됩니다. - Width/Height: 픽셀 단위; 높이 50‑80 픽셀은 대부분의 비즈니스 문서에 전문적으로 보입니다.
정렬 및 패딩을 어떻게 제어하나요?
정렬 설정은 스탬프가 페이지에 배치되는 위치를 결정하고, 패딩은 시각 요소 주변에 여백을 추가해 페이지 가장자리에 닿지 않도록 합니다. 적절한 정렬은 가독성을 높이고 서명이 기존 콘텐츠와 충돌하지 않도록 보장합니다.
AlignmentOptions는 Bottom, Right, Top, Center와 같은 수직 및 수평 배치 상수를 제공합니다.
options.setVerticalAlignment(VerticalAlignment.Bottom);
options.setHorizontalAlignment(HorizontalAlignment.Right);
options.setPadding(10);
- Padding: 스탬프 주변에 여유 공간을 추가합니다; 10 픽셀 값은 이미지가 페이지 가장자리에 닿는 것을 방지합니다.
- 실제 예시: 청구서 템플릿에서는
Top/Left를 사용해 승인자의 서명을 헤더 근처에 배치할 수 있습니다.
Office 문서에 서명 라인을 어떻게 추가하나요?
DOCX 또는 XLSX 파일에 서명할 때, 보이는 서명 라인은 최종 사용자의 가독성을 향상시킵니다. 라이브러리는 서명자의 이름, 직함, 이메일을 표시하는 Microsoft 스타일 서명 라인을 생성하여 기본 Office 경험을 그대로 재현합니다.
SignatureLineOptions는 서명자의 이름, 직함, 이메일을 표시하는 Microsoft 스타일 서명 라인을 생성합니다.
options.setSignatureLineText("John Doe", "Chief Legal Officer", "j.doe@yourcompany.com");
- 이 기능은 PDF에서는 무시되지만 Microsoft Office에서 열리는 Word 및 Excel 파일에는 필수적입니다.
실제로 문서에 서명하려면 어떻게 하나요?
Signature 인스턴스로 소스 파일을 로드하고, 완전히 구성된 DigitalSignOptions를 적용한 뒤 sign()을 호출합니다. 라이브러리는 출력 경로에 새 파일을 작성하고 원본 파일은 그대로 둡니다. 대용량 PDF(50페이지 이상)의 경우 2‑5초 정도 처리 시간이 예상되며, 웹 서비스에서는 비동기 실행을 고려하십시오.
Signature signature = new Signature("SAMPLE_WORDPROCESSING/contract.docx");
DigitalSignOptions options = new DigitalSignOptions();
// ...configure options as shown earlier...
signature.sign("OUTPUT_FOLDER/signed_contract.docx", options);
성능 참고: 100페이지가 넘는 문서의 경우 JVM 힙(-Xmx2g)을 늘리거나 setAllPages(true)를 비활성화해 메모리 사용량을 제한하십시오.
일반적인 문제를 어떻게 해결하나요?
서명이 실패할 때 가장 흔한 문제는 인증서 처리, 시각적 배치 또는 메모리 제약과 관련됩니다. 증상을 파악한 뒤 아래 체크리스트를 따라 빠르게 문제를 해결하십시오.
“Invalid Certificate” 또는 “Cannot Load Certificate” 오류가 표시되는 이유는?
이 예외는 일반적으로 다음 네 가지 원인 중 하나에서 발생합니다:
- 잘못된 비밀번호 – OpenSSL로 확인하십시오:
openssl pkcs12 -info -in yourcert.pfx. - 만료된 인증서 –
keytool -list -v -keystore yourcert.pfx를 사용해 유효성을 확인하십시오. - 잘못된 파일 형식 – 개인 키를 포함하는
.pfx또는.p12만 허용됩니다. - 파일 권한 문제 – Java 프로세스가 인증서 파일을 읽을 수 있는지 확인하십시오.
서명이 페이지에 표시되지 않는 이유는?
- AllPages 플래그가
false일 수 있어 스탬프가 없는 페이지를 보고 있을 수 있습니다. - 이미지 경로가 오타일 수 있습니다;
options.getImageFilePath()를 출력해 확인하십시오. - 정렬 설정이 스탬프를 화면 밖으로 밀어낼 수 있습니다; 디버깅을 위해 일시적으로
Center로 전환하십시오.
Adobe Reader가 “Signature Invalid”를 보고하는 이유는?
- 인증서가 신뢰되지 않음 – 자체 서명 인증서는 경고를 발생시킵니다. 운영 환경에서는 CA가 발급한 인증서를 사용하십시오.
- 인증서 체인 불완전 –
.pfx에 중간 및 루트 인증서가 포함되어 있는지 확인하십시오. - 타임스탬프 누락 – TSA 토큰이 없으면 인증서가 만료된 후 서명이 무효로 간주될 수 있습니다. GroupDocs는
setTimeStampOptions()를 통해 타임스탬프를 지원합니다.
대용량 PDF에서 OutOfMemoryError를 방지하려면 어떻게 하나요?
- JVM 힙을 늘리십시오 (
-Xmx4g이상). - 필요한 페이지만 서명하십시오 (
setAllPages(false)). - 제한된 환경에서는 파일을 작은 배치로 처리하거나 스트리밍하십시오.
운영 환경에서 인증서를 안전하게 관리하려면 어떻게 하나요?
소스 코드에 인증서나 비밀번호를 절대 삽입하지 마십시오. 다음 단계를 따르세요:
.pfx파일을 안전한 금고(AWS Secrets Manager, Azure Key Vault, 또는 HashiCorp Vault)에 저장합니다.- 런타임에 환경 변수나 금고 API를 통해 비밀번호를 로드합니다.
- 파일 시스템 권한을 제한하여 서비스 계정만 인증서를 읽을 수 있도록 합니다.
- 인증서 만료 최소 30일 전에 교체하고 저장된 비밀을 업데이트합니다.
String certPath = System.getenv("CERT_PATH");
String certPassword = System.getenv("CERT_PASSWORD");
options.setCertificatePath(certPath);
options.setCertificatePassword(certPassword);
감사 준수를 위해 서명 작업을 어떻게 로그에 기록하나요?
감사 로그는 부인 방지 증거를 제공합니다. 각 서명 이벤트에 대해 다음 필드를 기록하십시오:
- 서명 전 문서 이름 및 해시
- 서명자 신원(인증서 주체)
- 작업 타임스탬프(가능하면 UTC)
- 결과 상태(성공/실패) 및 오류 세부 정보(있는 경우)
logger.info("Signing document {} with certificate {} at {}", docPath, options.getCertificatePath(), Instant.now());
적용된 서명을 어떻게 검증하나요?
검증은 서명 후 문서가 변조되지 않았는지 확인합니다. verify() 메서드를 사용하면 유효성 상태, 서명자 상세 정보 및 타임스탬프 정보를 포함하는 VerificationResult를 반환합니다. 성공적인 검증은 무결성과 진위성을 모두 확인합니다.
VerificationResult result = signature.verify("OUTPUT_FOLDER/signed_contract.docx");
if (result.isValid()) {
logger.info("Signature is valid and trusted.");
} else {
logger.warn("Signature verification failed: {}", result.getErrorMessage());
}
단일 문서에 여러 서명을 추가하려면 어떻게 하나요?
승인자와 증인 서명이 필요할 수 있습니다. 서로 다른 DigitalSignOptions 인스턴스를 사용해 sign()을 여러 번 호출하면 각 서명은 자체 인증서와 시각 설정을 갖게 됩니다. 라이브러리는 기존 서명을 보존하면서 새 서명을 추가합니다.
// First signature (approver)
signature.sign("output.docx", approverOptions);
// Second signature (witness)
signature.sign("output.docx", witnessOptions);
다양한 문서 유형에 대한 팩터리 메서드를 어떻게 만들나요?
헬퍼 메서드는 파일 확장자를 기반으로 사전 구성된 DigitalSignOptions를 반환하여 코드를 DRY하게 유지합니다. 이는 PDF, Word, Excel 및 기타 지원 형식에 대한 인증서 로드, 시각 기본값 및 페이지 선택 로직을 중앙 집중화합니다.
public DigitalSignOptions getOptionsFor(String extension) {
DigitalSignOptions opts = new DigitalSignOptions();
// common settings
if (extension.equalsIgnoreCase("pdf")) {
opts.setImageFilePath("signatures/pdf_stamp.png");
} else if (extension.equalsIgnoreCase("docx")) {
opts.setSignatureLineText("Jane Smith", "Finance Manager", "j.smith@company.com");
}
return opts;
}
문서가 이미 서명되지 않았는지 어떻게 검증하나요?
새 서명을 적용하기 전에 기존 서명이 있는지 확인해 이중 서명을 방지하십시오. getSignatures() 메서드를 사용하고, 반환된 컬렉션이 비어 있지 않다면 새 서명을 추가할지 작업을 중단할지 결정하십시오.
List<SignatureInfo> existing = signature.getSignatures();
if (!existing.isEmpty()) {
logger.warn("Document already contains {} signatures.", existing.size());
}
실용적인 적용 사례 (실제 사용 사례)
- 자동 계약 워크플로우 – 계약이 BPM 시스템에서 “승인” 상태에 도달하면 서명 서비스를 트리거해 법무 부서의 인증서를 삽입하고 서명된 사본을 공급업체에 이메일로 전송합니다.
- 청구서 승인 시스템 – 재무 부서가 청구서에 서명한 후, 고객에게 보내기 전에 자동으로 디지털 서명을 추가하여 진위에 대한 암호화 증명을 제공합니다.
- 문서 검증 포털 – 사용자가 PDF를 업로드하면 회사 전체 인증서로 서명하고, 법적 준수를 위해 변조 방지 파일을 반환하는 셀프 서비스 포털을 제공합니다.
- 규제 준수가 중요한 산업 – 의료(HIPAA) 또는 금융(SOX) 분야에서 디지털 서명은 누가 언제 문서에 서명했는지를 증명함으로써 감사 요구 사항을 충족합니다.
- 내부 정책 배포 – HR 정책에 대한 수동 스탬프를 자동화된 프로세스로 대체하여 CHRO 인증서로 최종 PDF에 서명하고 모든 직원이 검증된 사본을 받도록 합니다.
성능 고려 사항
| 문서 크기 | 평균 처리 시간 | 권장 설정 |
|---|---|---|
| 1‑5 페이지 | ~0.5 s | 기본 옵션 |
| 5‑50 페이지 | 1‑3 s | 필요 시 힙 증가, setAllPages(true) |
| 50‑200 페이지 | 3‑10 s | setAllPages(false), 비동기 실행, 더 큰 힙 |
최적화 팁:
- 배치에서 다수의 파일을 서명할 때 단일
Signature인스턴스를 재사용하십시오. - 로드된
DigitalSignOptions객체를 캐시하십시오; 인증서를 반복 로드하면 오버헤드가 발생합니다. - 웹 서비스에서는 서명 호출을
CompletableFuture로 감싸거나 메시지 큐에 전달해 UI 응답성을 유지하십시오.
전문가 팁 (고급 사용법)
- 장기 유효성을 위한 타임스탬프 –
setTimeStampOptions()를 사용해 TSA 토큰을 첨부하면 인증서가 만료된 후에도 서명이 유효합니다. - 보이지 않는 서명 –
ImageFilePath를 생략하고Width/Height를0으로 설정하면 시각적 스탬프가 필요 없는 백엔드 프로세스에 적합한 암호학적으로 유효한 보이지 않는 서명을 만들 수 있습니다. - 맞춤형 QR 코드 서명 – GroupDocs는 서명자 메타데이터를 포함한 QR 코드를 삽입할 수 있어, 모바일 기기로 빠르게 검증해야 하는 공급망 문서에 이상적입니다.
자주 묻는 질문
Q: GroupDocs.Signature와 iText의 PDF 서명 주요 차이점은 무엇인가요?
A: iText는 PDF에만 초점을 맞추고 저수준 암호화를 직접 처리해야 하는 반면, GroupDocs.Signature는 30개 이상의 형식을 지원하고 즉시 사용할 수 있는 시각적 스탬프를 제공하며 인증서 처리를 추상화해 개발 시간을 크게 단축합니다.
Q: GroupDocs.Signature를 Spring Boot 마이크로서비스에 통합할 수 있나요?
A: 예. Maven 의존성을 추가하고 서명 로직을 감싸는 @Service 빈을 생성한 뒤 문서 서명이 필요한 곳에 주입하십시오. 이렇게 하면 컨트롤러는 가볍게 유지되고 서명 코드를 재사용할 수 있습니다.
Q: GroupDocs.Signature로 만든 서명의 보안성은 어느 정도인가요?
A: 라이브러리는 표준 PKI 알고리즘(RSA/ECDSA)을 사용하며 브라우저와 Adobe Reader와 동일한 사양을 따릅니다. 보안은 인증서 품질에 달려 있으므로 항상 CA가 발급한 인증서를 사용하고 개인 키를 보호하십시오.
Q: 서명된 문서는 다양한 PDF 리더에서 작동하나요?
A: 물론입니다. 서명 인증서가 신뢰되는 한 Adobe Reader, Foxit, 최신 브라우저 모두 서명을 올바르게 검증합니다. 자체 서명 인증서는 경고를 표시하지만 기술적으로는 유효합니다.
Q: 보이는 서명 이미지 없이 문서에 서명할 수 있나요?
A: 예—ImageFilePath를 생략하고 크기 매개변수를 0으로 설정하면 됩니다. 결과 서명은 보이지 않지만 암호학적으로 견고하여 시각적 표시가 필요 없는 백엔드 자동화에 적합합니다.
결론
이제 GroupDocs.Signature를 사용한 add digital signature java에 대한 완전하고 운영 준비가 된 로드맵을 갖추었습니다. 환경 설정 및 인증서 처리부터 시각적 맞춤화, 성능 튜닝, 다중 서명 및 타임스탬프와 같은 고급 시나리오까지 모두 다루었습니다.
다음 단계:
- 자체 인증서와 문서 템플릿으로 샘플 코드를 테스트하십시오.
- 인증서를 비밀 관리자로 이동하고 적절한 JVM 메모리 제한을 설정해 배포를 강화하십시오.
- 헬퍼 메서드를 확장해 배치 처리 지원하거나 기존 워크플로 엔진에 통합하십시오.
보다 깊이 있게 살펴보려면 아래 링크된 공식 문서와 커뮤니티 포럼을 확인하십시오.
마지막 업데이트: 2026-06-11
테스트 환경: GroupDocs.Signature 23.12 for Java
작성자: GroupDocs
import com.groupdocs.signature.Signature;
public class SignatureSetup {
public static void main(String[] args) {
Signature signature = new Signature("path/to/your/document");
// Your signing logic goes here
}
}
import com.groupdocs.signature.options.sign.DigitalSignOptions;
import com.groupdocs.signature.domain.enums.HorizontalAlignment;
import com.groupdocs.signature.domain.enums.VerticalAlignment;
import com.groupdocs.signature.exception.GroupDocsSignatureException;
DigitalSignOptions options = new DigitalSignOptions("YOUR_DOCUMENT_DIRECTORY/CertificatePfx");
options.setPassword("1234567890"); // Ensure your certificate password is secure
options.setReason("Sign"); // Reason for signing, e.g., "Contract Approval"
options.setContact("JohnSmith"); // Contact information of the signer
options.setLocation("Office1"); // Location where document is signed
options.setImageFilePath("YOUR_DOCUMENT_DIRECTORY/ImageHandwrite");
options.setAllPages(true); // Apply signature to all pages of the document
options.setWidth(0); // Auto-width based on content
options.setHeight(60); // Height in pixels
options.setVerticalAlignment(VerticalAlignment.Bottom);
options.setHorizontalAlignment(HorizontalAlignment.Right);
Padding padding = new Padding();
padding.setBottom(10); // Bottom padding for aesthetic spacing
padding.setRight(10); // Right padding to prevent clipping at edges
options.setMargin(padding);
import com.groupdocs.signature.domain.signatures.DigitalSignatureAppearance;
options.setAppearance(new DigitalSignatureAppearance("John Smith", "Title", "jonny@test.com"));
try {
Signature signature = new Signature("YOUR_DOCUMENT_DIRECTORY/SAMPLE_WORDPROCESSING");
String outputFilePath = "YOUR_OUTPUT_DIRECTORY/DigitalAppearance.docx";
signature.sign(outputFilePath, options);
} catch (GroupDocsSignatureException e) {
throw new RuntimeException(e.getMessage());
}
// BAD - Don't do this
options.setPassword("1234567890");
// GOOD - Load from environment variable
String certPassword = System.getenv("CERT_PASSWORD");
if (certPassword == null) {
throw new RuntimeException("CERT_PASSWORD environment variable not set");
}
options.setPassword(certPassword);
logger.info("Document signed: {}, SignedBy: {}, Timestamp: {}",
documentName, signerEmail, LocalDateTime.now());
// Verify the signature immediately after signing
List<DigitalSignature> signatures = signature.verify();
if (signatures.isEmpty()) {
throw new RuntimeException("Signature verification failed");
}
signature.sign(outputPath, approverOptions);
signature = new Signature(outputPath); // Reload the signed document
signature.sign(finalOutputPath, witnessOptions);
public DigitalSignOptions getOptionsForDocType(String docType) {
DigitalSignOptions options = new DigitalSignOptions(certPath);
if (docType.equals("contract")) {
options.setVerticalAlignment(VerticalAlignment.Bottom);
// Contract-specific settings
} else if (docType.equals("invoice")) {
options.setVerticalAlignment(VerticalAlignment.Top);
// Invoice-specific settings
}
return options;
}
List<DigitalSignature> existingSignatures = signature.search(DigitalSignature.class);
if (!existingSignatures.isEmpty()) {
System.out.println("Document already signed by: " +
existingSignatures.get(0).getContactInfo());
}