https://itextpdf.com/book/digitalsignaturesのサンプル 3.1 とコード サンプル 3.2 から適合したサンプル コードを取得しようとする iText の新規ユーザー
参考までにコード スニペットを含めました。
ホスティング プロバイダー.pfx
に GlobalSign 証明書からファイルを作成してもらいました (.p12
ファイルは提供されません)。彼らは次の Linux コマンドを発行しました。
# openssl pkcs12 -export -out cert.pfx -inkey www.mydomain.com.key
-in ../certs/www.mydomain.com.crt -certfile ../certs/ca-bundle.crt
グローバルサインからどこにca-bundle.crt
来ますか。を取得するために、ファイルを拡張子付きの新しいファイルに.p12
コピーしました。私がオンラインで見ることができることから、ファイルとファイルはバイナリ同等であるため、人々は以前にこれを行い(iTextとは関係ありません)、成功しました。.pfx
.p12
.pfx
.p12
確認するには、Linux プロンプトで次のように入力します。
openssl pkcs12 -info -in /path/to/file/cert.pfx
次に、インポート パスワードを要求されますが、何もないので、Enter キーを押すだけで、入力するプライベート パス フレーズを要求されます (例: myPrivateCertPassword
)。秘密鍵。
ここで私は混乱します。インポート パスワードがないため、iText で次の試行を試みました (以下のスニペットに示すように)。
ks.load(new FileInputStream(CONSTANTS.CERTIFICATE_PATH), null);
ks.load(new FileInputStream(CONSTANTS.CERTIFICATE_PATH), "".toCharArray());
どちらも機能しません。最初の実行時エラーが発生します。
java.io.IOException: PKCS12 key store mac invalid - wrong password or corrupted file.
そして2番目のものは実行時エラーを与えます:
java.lang.NoClassDefFoundError : org/bouncycastle/cert/X509CertificateHolder
何が間違っている可能性がありますか?
正確には、コード行で使用されているパスワードはどこks.load()
から来たのですか (GlobalSign? サーバー ホスティング会社? 私?)。export key
これは、上記の export コマンドを発行したときに呼び出されますか?
コメントをお寄せいただきありがとうございます。
-------- コード スニペットが続きます ----------
public static final char[] PASS = "myPrivateCertPassword".toCharArray();
public static final String CERTIFICATE_PATH = "/path/to/file/cert.p12";
main() で:
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(CONSTANTS.CERTIFICATE_PATH), null);
// ks.load(new FileInputStream(CONSTANTS.CERTIFICATE_PATH), "".toCharArray()); // this also fails
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, CONSTANTS.PASS);
Certificate[] chain = ks.getCertificateChain(alias);
sign(userFile, userFile_signed, chain, pk, DigestAlgorithms.SHA256,
provider.getName(),CryptoStandard.CMS, "Test", "Ghent", null, null, null, 0);
main() の外側:
public void sign(
String src,
String dest,
Certificate[] chain,
PrivateKey pk,
String digestAlgorithm,
String provider,
CryptoStandard subfilter,
String reason,
String location,
Collection<CrlClient> crlList,
OcspClient ocspClient, TSAClient tsaClient,
int estimatedSize)
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(new Rectangle(36, 748, 144, 780), 1, "sig");
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain,
crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
更新 1:
上記のようにエクスポートして新しい cert.pfx ファイルを作成しましたが、今回は「エクスポート パスワード」を として入力し、次のようexportPassword
に挿入しました。
ks.load(new FileInputStream(CONSTANTS.CERTIFICATE_PATH), "exportPassword".toCharArray());
しかし、これにより新しい実行時エラーが発生します。
java.io.IOException: exception decrypting data - java.security.InvalidKeyException: Illegal key size
私は近づいていますか?
更新 2:
Bruno のコメントに従って JCE をインストールしたところ、次のエラーが発生しました。
java.lang.NoClassDefFoundError : org/bouncycastle/tsp/TimeStampTokenInfo
更新 3:
上記のエラーは、www.bouncycastle.org の bcpkix-jdk15on-149.jar を /lib ディレクトリに追加し、Java プログラムに以下を追加することで解決できました。
import org.bouncycastle.jce.provider.BouncyCastleProvider; // this was already there
import org.bouncycastle.tsp.TimeStampTokenInfo; // this is new and fixed the above error
デジタル署名が表示されるようになりました。
更新 4:
興味のある方は、こちらのフォローアップ投稿を参照してください: iText: what type of certificates do people use to auto PDF signing on Linux?