📄 pdfpkcs7.java
字号:
}
}
if (j == certs.length)
return new Object[]{cert, "Cannot be verified against the KeyStore or the certificate chain"};
}
return new Object[]{null, "Invalid state. Possible circular certificate chain"};
}
/**
* Get the "issuer" from the TBSCertificate bytes that are passed in
* @param enc a TBSCertificate in a byte array
* @return a DERObject
*/
private static DERObject getIssuer(byte[] enc) {
try {
ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(enc));
ASN1Sequence seq = (ASN1Sequence)in.readObject();
return (DERObject)seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 3 : 2);
}
catch (IOException e) {
throw new ExceptionConverter(e);
}
}
/**
* Get the "subject" from the TBSCertificate bytes that are passed in
* @param enc A TBSCertificate in a byte array
* @return a DERObject
*/
private static DERObject getSubject(byte[] enc) {
try {
ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(enc));
ASN1Sequence seq = (ASN1Sequence)in.readObject();
return (DERObject)seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 5 : 4);
}
catch (IOException e) {
throw new ExceptionConverter(e);
}
}
/**
* Get the issuer fields from an X509 Certificate
* @param cert an X509Certificate
* @return an X509Name
*/
public static X509Name getIssuerFields(X509Certificate cert) {
try {
return new X509Name((ASN1Sequence)getIssuer(cert.getTBSCertificate()));
}
catch (Exception e) {
throw new ExceptionConverter(e);
}
}
/**
* Get the subject fields from an X509 Certificate
* @param cert an X509Certificate
* @return an X509Name
*/
public static X509Name getSubjectFields(X509Certificate cert) {
try {
return new X509Name((ASN1Sequence)getSubject(cert.getTBSCertificate()));
}
catch (Exception e) {
throw new ExceptionConverter(e);
}
}
/**
* Gets the bytes for the PKCS#1 object.
* @return a byte array
*/
public byte[] getEncodedPKCS1() {
try {
if (externalDigest != null)
digest = externalDigest;
else
digest = sig.sign();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ASN1OutputStream dout = new ASN1OutputStream(bOut);
dout.writeObject(new DEROctetString(digest));
dout.close();
return bOut.toByteArray();
}
catch (Exception e) {
throw new ExceptionConverter(e);
}
}
/**
* Sets the digest/signature to an external calculated value.
* @param digest the digest. This is the actual signature
* @param RSAdata the extra data that goes into the data tag in PKCS#7
* @param digestEncryptionAlgorithm the encryption algorithm. It may must be <CODE>null</CODE> if the <CODE>digest</CODE>
* is also <CODE>null</CODE>. If the <CODE>digest</CODE> is not <CODE>null</CODE>
* then it may be "RSA" or "DSA"
*/
public void setExternalDigest(byte digest[], byte RSAdata[], String digestEncryptionAlgorithm) {
externalDigest = digest;
externalRSAdata = RSAdata;
if (digestEncryptionAlgorithm != null) {
if (digestEncryptionAlgorithm.equals("RSA")) {
this.digestEncryptionAlgorithm = ID_RSA;
}
else if (digestEncryptionAlgorithm.equals("DSA")) {
this.digestEncryptionAlgorithm = ID_DSA;
}
else
throw new ExceptionConverter(new NoSuchAlgorithmException("Unknown Key Algorithm "+digestEncryptionAlgorithm));
}
}
/**
* Gets the bytes for the PKCS7SignedData object.
* @return the bytes for the PKCS7SignedData object
*/
public byte[] getEncodedPKCS7() {
return getEncodedPKCS7(null, null);
}
/**
* Gets the bytes for the PKCS7SignedData object. Optionally the authenticatedAttributes
* in the signerInfo can also be set. If either of the parameters is <CODE>null</CODE>, none will be used.
* @param secondDigest the digest in the authenticatedAttributes
* @param signingTime the signing time in the authenticatedAttributes
* @return the bytes for the PKCS7SignedData object
*/
public byte[] getEncodedPKCS7(byte secondDigest[], Calendar signingTime) {
try {
if (externalDigest != null) {
digest = externalDigest;
if (RSAdata != null)
RSAdata = externalRSAdata;
}
else if (externalRSAdata != null && RSAdata != null) {
RSAdata = externalRSAdata;
sig.update(RSAdata);
digest = sig.sign();
}
else {
if (RSAdata != null) {
RSAdata = messageDigest.digest();
sig.update(RSAdata);
}
digest = sig.sign();
}
// Create the set of Hash algorithms
DERConstructedSet digestAlgorithms = new DERConstructedSet();
for(Iterator it = digestalgos.iterator(); it.hasNext();) {
ASN1EncodableVector algos = new ASN1EncodableVector();
algos.add(new DERObjectIdentifier((String)it.next()));
algos.add(new DERNull());
digestAlgorithms.addObject(new DERSequence(algos));
}
// Create the contentInfo.
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(ID_PKCS7_DATA));
if (RSAdata != null)
v.add(new DERTaggedObject(0, new DEROctetString(RSAdata)));
DERSequence contentinfo = new DERSequence(v);
// Get all the certificates
//
v = new ASN1EncodableVector();
for (Iterator i = certs.iterator(); i.hasNext();) {
ASN1InputStream tempstream = new ASN1InputStream(new ByteArrayInputStream(((X509Certificate)i.next()).getEncoded()));
v.add(tempstream.readObject());
}
DERSet dercertificates = new DERSet(v);
// Create signerinfo structure.
//
ASN1EncodableVector signerinfo = new ASN1EncodableVector();
// Add the signerInfo version
//
signerinfo.add(new DERInteger(signerversion));
v = new ASN1EncodableVector();
v.add(getIssuer(signCert.getTBSCertificate()));
v.add(new DERInteger(signCert.getSerialNumber()));
signerinfo.add(new DERSequence(v));
// Add the digestAlgorithm
v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(digestAlgorithm));
v.add(new DERNull());
signerinfo.add(new DERSequence(v));
// add the authenticated attribute if present
if (secondDigest != null && signingTime != null) {
ASN1EncodableVector attribute = new ASN1EncodableVector();
v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(ID_CONTENT_TYPE));
v.add(new DERSet(new DERObjectIdentifier(ID_PKCS7_DATA)));
attribute.add(new DERSequence(v));
v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(ID_SIGNING_TIME));
v.add(new DERSet(new DERUTCTime(signingTime.getTime())));
attribute.add(new DERSequence(v));
v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(ID_MESSAGE_DIGEST));
v.add(new DERSet(new DEROctetString(secondDigest)));
attribute.add(new DERSequence(v));
if (!crls.isEmpty()) {
v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(ID_ADBE_REVOCATION));
ASN1EncodableVector v2 = new ASN1EncodableVector();
for (Iterator i = crls.iterator();i.hasNext();) {
ASN1InputStream t = new ASN1InputStream(new ByteArrayInputStream((((X509CRL)i.next()).getEncoded())));
v2.add(t.readObject());
}
v.add(new DERSet(new DERSequence(new DERTaggedObject(true, 0, new DERSequence(v2)))));
attribute.add(new DERSequence(v));
}
signerinfo.add(new DERTaggedObject(false, 0, new DERSet(attribute)));
}
// Add the digestEncryptionAlgorithm
v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(digestEncryptionAlgorithm));
v.add(new DERNull());
signerinfo.add(new DERSequence(v));
// Add the digest
signerinfo.add(new DEROctetString(digest));
// Finally build the body out of all the components above
ASN1EncodableVector body = new ASN1EncodableVector();
body.add(new DERInteger(version));
body.add(digestAlgorithms);
body.add(contentinfo);
body.add(new DERTaggedObject(false, 0, dercertificates));
if (!crls.isEmpty()) {
v = new ASN1EncodableVector();
for (Iterator i = crls.iterator();i.hasNext();) {
ASN1InputStream t = new ASN1InputStream(new ByteArrayInputStream((((X509CRL)i.next()).getEncoded())));
v.add(t.readObject());
}
DERSet dercrls = new DERSet(v);
body.add(new DERTaggedObject(false, 1, dercrls));
}
// Only allow one signerInfo
body.add(new DERSet(new DERSequence(signerinfo)));
// Now we have the body, wrap it in it's PKCS7Signed shell
// and return it
//
ASN1EncodableVector whole = new ASN1EncodableVector();
whole.add(new DERObjectIdentifier(ID_PKCS7_SIGNED_DATA));
whole.add(new DERTaggedObject(0, new DERSequence(body)));
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ASN1OutputStream dout = new ASN1OutputStream(bOut);
dout.writeObject(new DERSequence(whole));
dout.close();
return bOut.toByteArray();
}
catch (Exception e) {
throw new ExceptionConverter(e);
}
}
/**
* When using authenticatedAttributes the authentication process is different.
* The document digest is generated and put inside the attribute. The signing is done over the DER encoded
* authenticatedAttributes. This method provides that encoding and the parameters must be
* exactly the same as in {@link #getEncodedPKCS7(byte[],Calendar)}.
* <p>
* A simple example:
* <p>
* <pre>
* Calendar cal = Calendar.getInstance();
* PdfPKCS7 pk7 = new PdfPKCS7(key, chain, null, "SHA1", null, false);
* MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
* byte buf[] = new byte[8192];
* int n;
* InputStream inp = sap.getRangeStream();
* while ((n = inp.read(buf)) > 0) {
* messageDigest.update(buf, 0, n);
* }
* byte hash[] = messageDigest.digest();
* byte sh[] = pk7.getAuthenticatedAttributeBytes(hash, cal);
* pk7.update(sh, 0, sh.length);
* byte sg[] = pk7.getEncodedPKCS7(hash, cal);
* </pre>
* @param secondDigest the content digest
* @param signingTime the signing time
* @return the byte array representation of the authenticatedAttributes ready to be signed
*/
public byte[] getAuthenticatedAttributeBytes(byte secondDigest[], Calendar signingTime) {
try {
ASN1EncodableVector attribute = new ASN1EncodableVector();
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(ID_CONTENT_TYPE));
v.add(new DERSet(new DERObjectIdentifier(ID_PKCS7_DATA)));
attribute.add(new DERSequence(v));
v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(ID_SIGNING_TIME));
v.add(new DERSet(new DERUTCTime(signingTime.getTime())));
attribute.add(new DERSequence(v));
v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(ID_MESSAGE_DIGEST));
v.add(new DERSet(new DEROctetString(secondDigest)));
attribute.add(new DERSequence(v));
if (!crls.isEmpty()) {
v = new ASN1EncodableVector();
v.add(new DERObjectIdentifier(ID_ADBE_REVOCATION));
ASN1EncodableVector v2 = new ASN1EncodableVector();
for (Iterator i = crls.iterator();i.hasNext();) {
ASN1InputStream t = new ASN1InputStream(new ByteArrayInputStream((((X509CRL)i.next()).getEncoded())));
v2.add(t.readObject());
}
v.add(new DERSet(new DERSequence(new DERTaggedObject(true, 0, new DERSequence(v2)))));
attribute.add(new DERSequence(v));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -