P7 Signature Implementation

Source: Internet
Author: User
Tags aliases constructor pkcs7 static class throw exception

Two types of P7 signatures1. Java JCEPackage encrypt;


Import Java.io.ByteArrayInputStream;
Import Java.io.ByteArrayOutputStream;
Import Java.io.FileInputStream;
Import java.io.IOException;
Import Java.io.InputStream;
Import Java.lang.reflect.Array;
Import Java.lang.reflect.Constructor;
Import Java.lang.reflect.Field;
Import Java.lang.reflect.Method;
Import Java.math.BigInteger;
Import java.security.GeneralSecurityException;
Import java.security.InvalidKeyException;
Import Java.security.KeyStore;
Import java.security.NoSuchAlgorithmException;
Import java.security.NoSuchProviderException;
Import Java.security.PrivateKey;
Import Java.security.Signature;
Import java.security.SignatureException;
Import Java.security.cert.Certificate;
Import java.security.cert.CertificateException;
Import Java.security.cert.CertificateFactory;
Import Java.security.cert.X509Certificate;
Import java.util.Enumeration;
Import Javax.security.auth.x500.X500Principal;
Import Sun.misc.BASE64Decoder;
Import Sun.misc.BASE64Encoder;
Import Sun.security.pkcs.ContentInfo;
Import sun.security.pkcs.PKCS7;
Import sun.security.pkcs.PKCS9Attributes;
Import Sun.security.pkcs.SignerInfo;


/**
* Pkcs7tool.java PKCS7 Format Signature Tool
*
* @version 1.0
* @author SUNY written date:2008-9-23 Modified Date 2010-6-12 Update for IBM
* JDK
*/
public class Pkcs7tool {
/** Signature */
private static final int signer = 1;
/** Verification */
private static final int VERIFIER = 2;
/** Use */
private int mode = 0;
/** Digest Algorithm */
Private String Digestalgorithm = "SHA1";
/** Signature Algorithm */
Private String Signingalgorithm = "Sha1withrsa";
/** Signing certificate Chain */
Private x509certificate[] certificates = null;
/** Signing Private Key */
Private Privatekey privatekey = null;
/** Root Certificate */
Private Certificate rootcertificate = null;
/** JVM Provider */
private static char, JVM = 0;
private static Class algorithmid = null;
private static Class dervalue = null;
private static Class objectidentifier = null;
private static Class x500name = null;
private static Boolean debug = FALSE;


/**
* Private Construction method
*/
Private Pkcs7tool (int mode) {
This.mode = mode;
}


/**
* Get signature tool to load Certificate library, get signing certificate chain and private key
*
* @param Keystorepath
* Certificate Library Path
* @param Keystorepassword
* Certificate Store password
* @throws generalsecurityexception
* @throws IOException
*/
public static Pkcs7tool Getsigner (String Keystorepath,
String Keystorepassword, String Keypassword)
Throws Generalsecurityexception, IOException {
Init ();
Load Certificate Library
KeyStore KeyStore = null;
if (Keystorepath.tolowercase (). EndsWith (". pfx"))
KeyStore = Keystore.getinstance ("PKCS12");
Else
KeyStore = Keystore.getinstance ("JKS");
FileInputStream FIS = null;
try {
FIS = new FileInputStream (Keystorepath);
Keystore.load (FIS, Keystorepassword.tochararray ());
} finally {
if (FIS! = null)
Fis.close ();
}
Locate the signature private key in the certificate store
Enumeration aliases = Keystore.aliases ();
String keyalias = null;
if (aliases! = null) {
while (Aliases.hasmoreelements ()) {
Keyalias = (String) aliases.nextelement ();
certificate[] certs = Keystore.getcertificatechain (Keyalias);
if (certs = = NULL | | certs.length = = 0)
Continue
X509Certificate cert = (x509certificate) certs[0];
if (Matchusage (Cert.getkeyusage (), 1)) {
try {
Cert.checkvalidity ();
} catch (Certificateexception e) {
Continue
}
Break
}
}
}
No available signature private key found
if (Keyalias = = null)
throw New Generalsecurityexception (
"None certificate for sign on this keystore");
if (Debug)
System.out.println (Keyalias);
x509certificate[] certificates = null;
if (Keystore.iskeyentry (Keyalias)) {
Check the certificate chain
certificate[] certs = Keystore.getcertificatechain (Keyalias);
for (int i = 0; i < certs.length; i++) {
if (! ( Certs[i] instanceof X509Certificate))
throw new Generalsecurityexception ("certificate[" + I
+ "] in chain '" + Keyalias
+ "is not a x509certificate.");
}
Convert certificate Chain
Certificates = new X509certificate[certs.length];
for (int i = 0; i < certs.length; i++)
Certificates[i] = (x509certificate) certs[i];
} else if (Keystore.iscertificateentry (Keyalias)) {
Only a single certificate
Certificate cert = keystore.getcertificate (Keyalias);
if (cert instanceof X509Certificate) {
Certificates = new x509certificate[] {(x509certificate) cert};
}
} else {
throw New Generalsecurityexception (Keyalias
+ "is unknown to this keystore");
}
Privatekey Privatekey = (privatekey) keystore.getkey (Keyalias,
Keypassword.tochararray ());
No private key Throw exception
if (Privatekey = = null) {
throw New Generalsecurityexception (Keyalias
+ "could not being accessed");
}
Pkcs7tool tool = new Pkcs7tool (signer);
Tool.certificates = certificates;
Tool.privatekey = Privatekey;
return tool;
}


/**
* Obtain a signature tool to load the trust root certificate
*
* @param Rootcertificatepath
* Root Certificate path
* @throws generalsecurityexception
* @throws IOException
*/
public static Pkcs7tool Getverifier (String rootcertificatepath)
Throws Generalsecurityexception, IOException {
Init ();
Load Root Certificate
FileInputStream FIS = null;
Certificate rootcertificate = null;
try {
FIS = new FileInputStream (Rootcertificatepath);
Certificatefactory certificatefactory = certificatefactory
. getinstance ("the");
try {
Rootcertificate = Certificatefactory.generatecertificate (FIS);
} catch (Exception Exception) {
InputStream is = new Bytearrayinputstream (
New Base64decoder (). Decodebuffer (FIS));
Rootcertificate = Certificatefactory.generatecertificate (IS);
}
} finally {
if (FIS! = null)
Fis.close ();
}
Pkcs7tool tool = new Pkcs7tool (VERIFIER);
Tool.rootcertificate = rootcertificate;
return tool;
}


/**
* Signature
*
* @param data
* Data
* @return Signature Signature Results
* @throws generalsecurityexception
* @throws IOException
* @throws IllegalArgumentException
*/
Public String sign (byte[] data) throws Exception {
if (mode! = signer)
throw New IllegalStateException (
"Call a Pkcs7tool instance isn't for signature.");
Signature signer = signature.getinstance (signingalgorithm);
Signer.initsign (Privatekey);
Signer.update (data, 0, data.length);
byte[] signedattributes = Signer.sign ();
ContentInfo contentinfo = null;
Field Data_oidfield = ContentInfo.class.getField ("data_oid");
Object data_oid = Data_oidfield.get (null);
Constructor Contentinfoconstructor = Contentinfo.class
. GetConstructor (New class[] {data_oid.getclass (), dervalue});
ContentInfo = (contentinfo) contentinfoconstructor
. newinstance (New object[] {data_oid, null});
Root certificate
X509Certificate x509 = certificates[certificates.length-1];
Java.math.BigInteger serial = X509.getserialnumber ();
X500name
Constructor X500nameconstructor = X500name
. GetConstructor (New class[] {string.class});
Object X500nameobject = X500nameconstructor
. newinstance (New object[] {X509.getissuerdn (). GetName ()});
Algorithmid
Method algorithmidget = Algorithmid.getmethod ("Get",
New class[] {string.class});
Object digestalgorithmid = Algorithmidget.invoke (null,
New object[] {digestalgorithm});
Field Algorithmidfield = Algorithmid.getfield ("rsaencryption_oid");
Object rsaoid = Algorithmidfield.get (null);
Constructor Algorithmconstructor = Algorithmid
. GetConstructor (New class[] {objectidentifier});
Object algorithmrsaoid = Algorithmconstructor
. newinstance (New object[] {rsaoid});
SignerInfo
Constructor Signerinfoconstructor = Signerinfo.class
. GetConstructor (New class[] {x500name, Biginteger.class,
Algorithmid, Pkcs9attributes.class, Algorithmid,
Byte[].class, pkcs9attributes.class});
Signature information
SignerInfo si = (signerinfo) signerinfoconstructor
. newinstance (New object[] {x500nameobject,//x500name,
Issuername,
Serial,//X509.getserialnumber (), BigInteger serial,
Digestalgorithmid,//Algorithmid, Digestalgorithmid,
NULL,//Pkcs9attributes, Authenticatedattributes,
Algorithmrsaoid,//Algorithmid,
Digestencryptionalgorithmid,
Signedattributes,//byte[] encrypteddigest,
Null//Pkcs9attributes unauthenticatedattributes)
});
Signerinfo[] Signerinfos = {SI};
Constructing PKCS7 Data
Object digestalgorithmids = Array.newinstance (Algorithmid, 1);
Array.set (digestalgorithmids, 0, Digestalgorithmid);
PKCS7
Constructor pkcs7constructor = PKCS7.class.getConstructor (new class[] {
Digestalgorithmids.getclass (), Contentinfo.class,
X509certificate[].class, Signerinfos.getclass ()});
PKCS7 P7 = (PKCS7) pkcs7constructor.newinstance (new object[] {
Digestalgorithmids, ContentInfo, certificates, Signerinfos});
PKCS7 P7 = new PKCS7 (Digestalgorithmids, ContentInfo, certificates,
Signerinfos);
Public PKCS7 (com.ibm.security.x509.algorithmid[] arg0,
Sun.security.pkcs.ContentInfo Arg1,
Java.security.cert.x509certificate[] Arg2,
Sun.security.pkcs.signerinfo[] arg3);
Public PKCS7 (sun.security.x509.algorithmid[] arg0,
Sun.security.pkcs.ContentInfo Arg1,
Java.security.cert.x509certificate[] Arg2,
Sun.security.pkcs.signerinfo[] arg3);
Bytearrayoutputstream baout = new Bytearrayoutputstream ();
P7.encodesigneddata (baout);
BASE64 encoding
Return (new Base64encoder ()). Encode (Baout.tobytearray ());
}


/**
* Verify signature (no CRL)
*
* @param signature
* Signature Signature Results
* @param data
* Signed Data
* @param DN
* Signature Certificate DN, if empty, does not match authentication
* @throws IOException
* @throws nosuchalgorithmexception
* @throws signatureexception
* @throws InvalidKeyException
* @throws certificateexception
* @throws nosuchproviderexception
*/
public void Verify (string signature, byte[] data, string dn)
Throws IOException, NoSuchAlgorithmException, Signatureexception,
InvalidKeyException, Certificateexception, nosuchproviderexception {
if (mode! = VERIFIER)
throw New IllegalStateException (
"Call a Pkcs7tool instance isn't for verify.");
byte[] Sign = new Base64decoder (). Decodebuffer (signature);
PKCS7 P7 = new PKCS7 (sign);
x509certificate[] certs = P7.getcertificates ();
if (Debug)
for (int i = 0; i < certs.length; i++) {
X509Certificate cert = certs[i];
System.out.println ("signer" + i + "=\n" + cert);
System.out.println ("signer" + i + "=\n"
+ New Base64encoder (). Encode (cert.getencoded ()));
}
Verifying the signature itself, certificate usage, certificate extensions
Signerinfo[] sis = p7.verify (data);
Check the results of the verification
if (sis = = null)
throw New Signatureexception (
"Signature failed verification, data has been tampered");
for (int i = 0; i < sis.length; i++) {
SignerInfo si = sis[i];
X509Certificate cert = si.getcertificate (P7);
Whether the certificate expires validation if no system date is available cert.checkvalidity (date);
Cert.checkvalidity ();
if (!cert.equals (rootcertificate)) {
Verifying certificate Signing
Cert.verify (Rootcertificate.getpublickey ());
}
Verify DN
if (i = = 0 && DN = null) {
X500principal name = Cert.getsubjectx500principal ();
if (!dn.equals (Name.getname (x500principal.rfc1779))
&&!new X500principal (DN). Equals (name))
throw new Signatureexception ("Signer dn")
+ Name.getname (x500principal.rfc1779)
+ "' does not matchs '" + DN + "'");
}
}
}


/**
* Match private key usage
*
* @param keyusage
* @param usage
* @return
*/
private static Boolean Matchusage (boolean[] keyusage, int usage) {
if (Usage = = 0 | | keyusage = = NULL)
return true;
for (int i = 0; i < math.min (keyusage.length); i++) {
if (Usage & (1 << i) = = 0 &&!keyusage[i])
return false;
}
return true;
}


private static void Init () {
if (JVM! = 0)
Return
String vendor = System.getproperty ("Java.vm.vendor");
if (vendor = = NULL)
Vendor = "";
String Vendoruc = Vendor.touppercase ();
try {
if (Vendoruc.indexof ("SUN") >= 0) {
JVM = ' S ';
Algorithmid = Class.forName ("Sun.security.x509.AlgorithmId");
Dervalue = Class.forName ("Sun.security.util.DerValue");
Objectidentifier = Class
. forname ("Sun.security.util.ObjectIdentifier");
X500name = Class.forName ("Sun.security.x509.X500Name");
} else if (Vendoruc.indexof ("IBM") >= 0) {
JVM = ' I ';
Algorithmid = Class
. forname ("Com.ibm.security.x509.AlgorithmId");
Dervalue = Class.forName ("Com.ibm.security.util.DerValue");
Objectidentifier = Class
. forname ("Com.ibm.security.util.ObjectIdentifier");
X500name = Class.forName ("Com.ibm.security.x509.X500Name");
} else {
System.out.println ("Not the support JRE:" + vendor);
System.exit (-1);
}
} catch (ClassNotFoundException e) {
E.printstacktrace ();
System.exit (-1);
}
}


/**
* @return return to Digestalgorithm.
*/
Public final String Getdigestalgorithm () {
return digestalgorithm;
}


/**
* @param digestalgorithm
* The Digestalgorithm to be set.
*/
Public final void Setdigestalgorithm (String digestalgorithm) {
This.digestalgorithm = Digestalgorithm;
}


/**

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.