2014-04-23 2 views
1

itext와 스마트 카드가있는 pdf에 서명하고 싶습니다. 독자가 스마트 카드를 넣으면 자동으로 Windows가 저장소에 두 개의 인증서를 추가합니다. 나는 브루노 Lowagie의 책을 읽고 난 샘플 이미지와 다른 재료를 추가하기 위해 노력 :IText - Windows 인증서 저장소로 문서 서명

public static void main(String[] args) 
     throws GeneralSecurityException, IOException, DocumentException { 

    BouncyCastleProvider provider = new BouncyCastleProvider(); 
    Security.addProvider(provider); 

    KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI"); 
    //KeyStore ks = KeyStore.getInstance("PKCS11"); 
    ks.load(null, PASSWORD); 
    String alias = (String) ks.aliases().nextElement(); 
    PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD); 
    Certificate[] chain = ks.getCertificateChain(alias); 

    sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256, 
      provider.getName(), CryptoStandard.CMS, "Test 1", "Ghent", "signHere"); 
    sign(SRC, String.format(DEST, 2), chain, pk, DigestAlgorithms.SHA512, 
      provider.getName(), CryptoStandard.CMS, "Test 2", "Ghent", "signHere"); 
    sign(SRC, String.format(DEST, 3), chain, pk, DigestAlgorithms.SHA256, 
      provider.getName(), CryptoStandard.CADES, "Test 3", "Ghent", "signHere"); 
    sign(SRC, String.format(DEST, 4), chain, pk, DigestAlgorithms.RIPEMD160, 
      provider.getName(), CryptoStandard.CADES, "Test 4", "Ghent", "signHere"); 
} 

public static void sign(String src, String dest, Certificate[] chain, PrivateKey pk, 
     String digestAlgorithm, String provider, CryptoStandard subfilter, 
     String reason, String location, String fieldToSign) 
     throws GeneralSecurityException, IOException, DocumentException { 

    // Creating the reader and the stamper 
    PdfReader reader = new PdfReader(src); 
    FileOutputStream os = new FileOutputStream(dest); 
    PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0'); 

    // Creating the appearance 
    PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); 
    appearance.setReason(reason); 
    appearance.setLocation(location); 
    appearance.setVisibleSignature(fieldToSign); 
    appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS); 

    appearance.setImage(Image.getInstance(Params.imgPath)); 
    appearance.setImageScale(-1); 

    // Creating the signature 
    ExternalDigest digest = new BouncyCastleDigest(); 
    ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, provider); 

    MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, subfilter); 

} 

하지만 내가 얻을 것은 java.security.InvalidKeyException입니다 : 공급 키 (sun.security.mscapi.RSAPrivateKey) RSAPrivateKey 인스턴스가 아닙니다.

왜 sun.security.mscapi.RSAPrivateKey가 RSAPrivateKey 인스턴스가 아닌지? 내가 여기서 뭐하고 있는거야? BouncyCastle jars 1.49 및 1.50과 함께이 오류가 있습니다.

답변

1

문제는 당신이 서명을 만들 때 통과 공급자이다.

ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, provider); 

공급자가 ks.getProvider() getName() (또는 "SunMSCAPI 프로")하지 BouncyCastleProvider해야합니다.

+0

에 의해 제공되는 응답 전에 게시되었습니다. 공급자를 "SunMSCAPI"로 변경하면이 문제가 해결됩니다. D : D –

0

PrivateKeySignature의 생성자에서 제공자 이름을 "SunMSCAPI"로 변경하십시오.

+0

왜 downvote? 이것은 실제 솔루션입니다 !! @Rush –