你的位置:首页 > 软件开发 > Java > 常见数字证书类型

常见数字证书类型

发布时间:2017-12-05 00:00:47
1 数字证书1.1 概述  数字证书就是互联网通讯中标志通讯各方身份信息的一串数字,提供了一种在Internet上验证通信实体身份的方式,数字证书不是数字身份证,而是身份认证机构盖在数字身份证上的一个章或印(或者说加在数字身份证上的一个签名)。它是由权威机构——CA机构,又称为证 ...

常见数字证书类型

1 数字证书

1.1 概述

  数字证书就是互联网通讯中标志通讯各方身份信息的一串数字,提供了一种在Internet上验证通信实体身份的方式,数字证书不是数字身份证,而是身份认证机构盖在数字身份证上的一个章或印(或者说加在数字身份证上的一个签名)。它是由权威机构——CA机构,又称为证书授权(Certificate Authority)中心发行的,人们可以在网上用它来识别对方的身份。

2 证书格式

2.1 证书格式分类

分为2大类:密钥库(含私钥,也可能有公钥)和公钥证书(仅含公钥)

 2.1.1 密钥库文件格式【Keystore】

 格式     :  JKS
 扩展名  : .jks/.ks
 描述     : 【Java Keystore】密钥库的Java实现版本,provider为SUN
 特点     :  密钥库和私钥用不同的密码进行保护
 
 格式     :  JCEKS
 扩展名  :  .jce
 描述     : 【JCE Keystore】密钥库的JCE实现版本,provider为SUN JCE
 特点     :  相对于JKS安全级别更高,保护Keystore私钥时采用TripleDES
 
 格式     :  PKCS12
 扩展名  :  .p12/.pfx
 描述     : 【PKCS #12】个人信息交换语法标准
 特点     :  1、包含私钥、公钥及其证书
                2、密钥库和私钥用相同密码进行保护
 
 格式     :  BKS
 扩展名  : .bks
 描述     :  Bouncycastle Keystore】密钥库的BC实现版本,provider为BC
 特点     :  基于JCE实现
 
 格式     : UBER
 扩展名  : .ubr
 描述     : 【Bouncycastle UBER Keystore】密钥库的BC更安全实现版本,provider为BC

2.2.2 证书文件格式【Certificate】 

格式          :  DER 
扩展名       :  .cer/.crt/.rsa

描述          : 【ASN .1 DER】用于存放证书 
特点          :  不含私钥、二进制

格式          :  PKCS7 
扩展名       : .p7b/.p7r 
描述          : 【PKCS #7】加密信息语法标准

特点          : 1、p7b以树状展示证书链,不含私钥
                   2、p7r为CA对证书请求签名的回复,只能用于导入

格式          :  CMS 
扩展名       :  .p7c/.p7m/.p7s 
描述          : 【Cryptographic Message Syntax】 
特点          : 1、p7c只保存证书
                   2、p7m:signature with enveloped data
                   3、p7s:时间戳签名文件
 
格式          :  PEM
扩展名       : .pem 
描述          : 【Printable Encoded Message】 
特点          : 1、该编码格式在RFC1421中定义,其实PEM是【Privacy-Enhanced Mail】的简写,但他也同样广泛运用于密钥管理
                   2、ASCII文件
                   3、一般基于base 64编码

格式         :  PKCS10 
扩展名      : .p10/.csr 
描述         : 【PKCS #10】公钥加密标准【Certificate Signing Request】
特点         :  1、证书签名请求文件
                   2、ASCII文件
                   3、CA签名后以p7r文件回复

格式          :  SPC 
扩展名      : .pvk/.spc 
描述          : 【Software Publishing Certificate】 
特点          :  微软公司特有的双证书文件格式,经常用于代码签名,其中
                  1、pvk用于保存私钥
                  2、spc用于保存公钥 

2.3 常用证书文件格式

  CA中心普遍采用的规范是X.509[13]系列和PKCS系列,其中主要应用到了以下规范:

2.3.1 X.509(1993) 

  X.509是由国际电信联盟(ITU-T)制定的数字证书标准。在X.500确保用户名称惟一性的基础上,X.509为X.500用户名称提供了通信实体的鉴别机制,并规定了实体鉴别过程中广泛适用的证书语法和数据接口。 

  X.509的最初版本公布于1988年。X.509证书由用户公共密钥和用户标识符组成。此外还包括版本号、证书序列号、CA标识符、签名算法标识、签发者名称、证书有效期等信息。这一标准的最新版本是X.509 v3,它定义了包含扩展信息的数字证书。该版数字证书提供了一个扩展信息字段,用来提供更多的灵活性及特殊应用环境下所需的信息传送。 

  一个标准的X.509数字证书包含以下一些内容:

  证书的版本信息;
  证书的序列号,每个证书都有一个唯一的证书序列号;
  证书所使用的签名算法;
  证书的发行机构名称,命名规则一般采用X.500格式;
  证书的有效期,通用的证书一般采用UTC时间格式,它的计时范围为1950-2049;
  证书所有人的名称,命名规则一般采用X.500格式;
  证书所有人的公开密钥;
  证书发行者对证书的签名。  常见数字证书类型

2.3.2 PKCS系列标准 

  PKCS是由美国RSA数据安全公司及其合作伙伴制定的一组公钥密码学标准,其中包括证书申请、证书更新、证书作废表发布、扩展证书内容以及数字签名、数字信封的格式等方面的一系列相关协议。到1999年底,PKCS已经公布了以下标准: 

  PKCS#1:定义RSA公开密钥算法加密和签名机制,主要用于组织PKCS#7中所描述的数字签名和数字信封。 

  PKCS#3:定义Diffie-Hellman密钥交换协议。 

  PKCS#5:描述一种利用从口令派生出来的安全密钥加密字符串的方法。使用MD2或MD5 从口令中派生密钥,并采用DES-CBC模式加密。主要用于加密从一个计算机传送到另一个计算机的私人密钥,不能用于加密消息。 

  PKCS#6:描述了公钥证书的标准语法,主要描述X.509证书的扩展格式。 

  PKCS#7:定义一种通用的消息语法,包括数字签名和加密等用于增强的加密机制,PKCS#7与PEM兼容,所以不需其他密码操作,就可以将加密的消息转换成PEM消息。 

  PKCS#8:描述私有密钥信息格式,该信息包括公开密钥算法的私有密钥以及可选的属性集等。 

  PKCS#9:定义一些用于PKCS#6证书扩展、PKCS#7数字签名和PKCS#8私钥加密信息的属性类型。 

  PKCS#10:描述证书请求语法。 

  PKCS#11:称为Cyptoki,定义了一套独立于技术的程序设计接口,用于智能卡和PCMCIA卡之类的加密设备。 

  PKCS#12:描述个人信息交换语法标准。描述了将用户公钥、私钥、证书和其他相关信息打包的语法。 

  PKCS#13:椭圆曲线密码体制标准。 

  PKCS#14:伪随机数生成标准。 

  PKCS#15:密码令牌信息格式标准。 

2.3.3 数字证书文件格式(cer和pfx)的区别

  作为文件形式存在的证书一般有这几种格式:  1.带有私钥的证书由Public Key Cryptography Standards #12,PKCS#12标准定义,包含了公钥和私钥的二进制格式的证书形式,以pfx作为证书文件后缀名。  2.二进制编码的证书 证书中没有私钥,DER 编码二进制格式的证书文件,以cer作为证书文件后缀名。  3.Base64编码的证书证书中没有私钥,BASE64 编码格式的证书文件,也是以cer作为证书文件后缀名。  由定义可以看出,只有pfx格式的数字证书是包含有私钥的,cer格式的数字证书里面只有公钥没有私钥。 

3 java代码实现(读取证书密钥)

 1 package cn.mars.app.txn.xmmsi; 2  3 import java.io.BufferedReader; 4 import java.io.ByteArrayInputStream; 5 import java.io.ByteArrayOutputStream; 6 import java.io.FileInputStream; 7 import java.io.FileNotFoundException; 8 import java.io.IOException; 9 import java.io.InputStream; 10 import java.io.InputStreamReader; 11 import java.math.BigInteger; 12 import java.security.InvalidAlgorithmParameterException; 13 import java.security.InvalidKeyException; 14 import java.security.KeyFactory; 15 import java.security.KeyStore; 16 import java.security.KeyStoreException; 17 import java.security.NoSuchAlgorithmException; 18 import java.security.PrivateKey; 19 import java.security.PublicKey; 20 import java.security.Signature; 21 import java.security.SignatureException; 22 import java.security.UnrecoverableKeyException; 23 import java.security.cert.Certificate; 24 import java.security.cert.CertificateException; 25 import java.security.cert.CertificateFactory; 26 import java.security.cert.X509Certificate; 27 import java.security.spec.InvalidKeySpecException; 28 import java.security.spec.KeySpec; 29 import java.security.spec.PKCS8EncodedKeySpec; 30 import java.security.spec.RSAPrivateKeySpec; 31 import java.security.spec.RSAPublicKeySpec; 32 import java.security.spec.X509EncodedKeySpec; 33 import java.util.Enumeration; 34  35 import javax.crypto.BadPaddingException; 36 import javax.crypto.Cipher; 37 import javax.crypto.IllegalBlockSizeException; 38 import javax.crypto.NoSuchPaddingException; 39 import javax.crypto.SecretKey; 40 import javax.crypto.spec.IvParameterSpec; 41 import javax.crypto.spec.SecretKeySpec; 42  43 import org.apache.commons.codec.binary.Base64; 44 import org.apache.commons.lang.StringUtils; 45 import org.bouncycastle.asn1.ASN1InputStream; 46 import org.bouncycastle.asn1.ASN1Sequence; 47 import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure; 48 import org.bouncycastle.asn1.x509.RSAPublicKeyStructure; 49 /*import org.slf4j.Logger; 50 import org.slf4j.LoggerFactory;*/ 51 import cn.mars.common.component.logger.LOG; 52 import cn.mars.common.component.logger.LogFactory; 53 import cn.mars.app.txn.xmmsi.KeyUtil; 54  55 /** 56  * <strong>Title : CryptoUtil</strong><br> 57  * <strong>Description : 加解密工具类</strong><br> 58  * <strong>Create on : 2015-05-04</strong><br> 59  *  60  * @author linshangqing@cmbc.com.cn<br> 61 */ 62 public abstract class CryptoUtil { 63  /** 64   * 日志对象 65  */ 66  public static LOG logger = LogFactory.getLogger(CryptoUtil.class); 67  /** 68   * 数字签名函数入口 69   *  70   * @param plainBytes 71   *   待签名明文字节数组 72   * @param privateKey 73   *   签名使用私钥 74   * @param signAlgorithm 75   *   签名算法 76   * @return 签名后的字节数组 77   * @throws Exception  78  */ 79  public static byte[] digitalSign(byte[] plainBytes, PrivateKey privateKey, String signAlgorithm) throws Exception { 80   try { 81    Signature signature = Signature.getInstance(signAlgorithm); 82    signature.initSign(privateKey); 83    signature.update(plainBytes); 84    byte[] signBytes = signature.sign(); 85  86    return signBytes; 87   } catch (NoSuchAlgorithmException e) { 88    throw new Exception(String.format("数字签名时没有[%s]此类算法", signAlgorithm)); 89    //throw new Exception(String.format("数字签名时没有[%s]此类算法", signAlgorithm)); 90   } catch (InvalidKeyException e) { 91    throw new Exception("数字签名时私钥无效"); 92   } catch (SignatureException e) { 93    throw new Exception("数字签名时出现异常"); 94   } 95  } 96  97  /** 98   * 验证数字签名函数入口 99   * 100   * @param plainBytes101   *   待验签明文字节数组102   * @param signBytes103   *   待验签签名后字节数组104   * @param publicKey105   *   验签使用公钥106   * @param signAlgorithm107   *   签名算法108   * @return 验签是否通过109   * @throws Exception110  */111  public static boolean verifyDigitalSign(byte[] plainBytes, byte[] signBytes, PublicKey publicKey, String signAlgorithm) throws Exception {112   boolean isValid = false;113   try {114    Signature signature = Signature.getInstance(signAlgorithm);115    signature.initVerify(publicKey);116    signature.update(plainBytes);117    isValid = signature.verify(signBytes);118    return isValid;119   } catch (NoSuchAlgorithmException e) {120    throw new Exception(String.format("验证数字签名时没有[%s]此类算法", signAlgorithm));121   } catch (InvalidKeyException e) {122    throw new Exception("验证数字签名时公钥无效");123   } catch (SignatureException e) {124    throw new Exception("验证数字签名时出现异常");125   }126  }127 128  /**129   * 验证数字签名函数入口130   * 131   * @param plainBytes132   *   待验签明文字节数组133   * @param signBytes134   *   待验签签名后字节数组135   * @param publicKey136   *   验签使用公钥137   * @param signAlgorithm138   *   签名算法139   * @return 验签是否通过140   * @throws Exception141  */142  public static boolean verifyDigitalSign(byte[] plainBytes, byte[] signBytes, X509Certificate cert, String signAlgorithm) throws Exception {143   boolean isValid = false;144   try {145    Signature signature = Signature.getInstance(signAlgorithm);146    signature.initVerify(cert);147    signature.update(plainBytes);148    isValid = signature.verify(signBytes);149    return isValid;150   } catch (NoSuchAlgorithmException e) {151    throw new Exception(String.format("验证数字签名时没有[%s]此类算法", signAlgorithm));152   } catch (InvalidKeyException e) {153    throw new Exception("验证数字签名时公钥无效");154   } catch (SignatureException e) {155    throw new Exception("验证数字签名时出现异常");156   }157  }158  /**159   * 获取RSA公钥对象160   * 161   * @param filePath162   *   RSA公钥路径163   * @param fileSuffix164   *   RSA公钥名称,决定编码类型165   * @param keyAlgorithm166   *   密钥算法167   * @return RSA公钥对象168   * @throws Exception169  */170  public static PublicKey getRSAPublicKeyByFileSuffix(String filePath, String fileSuffix, String keyAlgorithm) throws Exception {171   InputStream in = null;172   String keyType = "";173   if ("crt".equalsIgnoreCase(fileSuffix) || "txt".equalsIgnoreCase(fileSuffix) ||"cer".equalsIgnoreCase(fileSuffix)) {174    keyType = "X.509";175   } else if ("pem".equalsIgnoreCase(fileSuffix)) {176    keyType = "PKCS12";177   } else if(("yljf").equalsIgnoreCase(fileSuffix)){178    keyType = "yljf";179   } else{180    keyType = "PKCS12";181   }182 183   try {184    in = new FileInputStream(filePath);185    PublicKey pubKey = null;186    if ("X.509".equals(keyType)) {187     CertificateFactory factory = CertificateFactory.getInstance(keyType);188     Certificate cert = factory.generateCertificate(in);189     pubKey = cert.getPublicKey();190    } else if ("PKCS12".equals(keyType)) {191     BufferedReader br = new BufferedReader(new InputStreamReader(in));192     StringBuilder sb = new StringBuilder();193     String readLine = null;194     while ((readLine = br.readLine()) != null) {195      if (readLine.charAt(0) == '-') {196       continue;197      } else {198       sb.append(readLine);199       sb.append('\r');200      }201     }202     X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(Base64.decodeBase64(sb.toString()));203     KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);204     pubKey = keyFactory.generatePublic(pubX509);205    }else if("yljf".equals(keyType)){206     BufferedReader br = new BufferedReader(new InputStreamReader(in, "utf-8"));207     String s = br.readLine();208     ASN1InputStream ain = new  ASN1InputStream(hexString2ByteArr(s));209     RSAPublicKeyStructure pStruct =  RSAPublicKeyStructure.getInstance(ain.readObject());210     RSAPublicKeySpec spec = new  RSAPublicKeySpec(pStruct.getModulus(),    pStruct.getPublicExponent());211     KeyFactory kf = KeyFactory.getInstance("RSA");212     if (in != null)213      in.close();214     return kf.generatePublic(spec);215    }216 217    return pubKey;218   } catch (FileNotFoundException e) {219    throw new Exception("公钥路径文件不存在");220   } catch (CertificateException e) {221    throw new Exception("生成证书文件错误");222   } catch (IOException e) {223    throw new Exception("读取公钥异常");224   } catch (NoSuchAlgorithmException e) {225    throw new Exception(String.format("生成密钥工厂时没有[%s]此类算法", keyAlgorithm));226   } catch (InvalidKeySpecException e) {227    throw new Exception("生成公钥对象异常");228   } finally {229    try {230     if (in != null) {231      in.close();232     }233    } catch (IOException e) {234    }235   }236  }237  238  /**239   * 240   * <br>description : 生成平台公钥证书对象241   * @param b242   * @return243   * @version  1.0244   * @date  2014-7-25上午11:56:05245  */246  private static X509Certificate getCert(String filePath) throws Exception {247   try {248    byte[] b = null;249    InputStream in = null;250    try{251     in = new FileInputStream(filePath);252     b = new byte[20480];253     in.read(b);254    }finally{255     if(null!=in)in.close();256    }257    ByteArrayInputStream bais = new ByteArrayInputStream(b);258    CertificateFactory cf = CertificateFactory.getInstance("X.509");259    X509Certificate x509Certificate = (X509Certificate)cf.generateCertificate(bais);260    return x509Certificate;261   } catch (Exception e) {262    logger.error("",e);263    throw new Exception("生成公钥证书对象异常");264   } 265  }266 267  /**268   * 获取RSA私钥对象269   * 270   * @param filePath271   *   RSA私钥路径272   * @param fileSuffix273   *   RSA私钥名称,决定编码类型274   * @param password275   *   RSA私钥保护密钥276   * @param keyAlgorithm277   *   密钥算法278   * @return RSA私钥对象279   * @throws Exception280  */281  @SuppressWarnings("deprecation")282  public static PrivateKey getRSAPrivateKeyByFileSuffix(String filePath, String fileSuffix, String password, String keyAlgorithm)283    throws Exception {284   String keyType = "";285   if ("keystore".equalsIgnoreCase(fileSuffix)) {286    keyType = "JKS";287   } else if ("pfx".equalsIgnoreCase(fileSuffix) || "p12".equalsIgnoreCase(fileSuffix)) {288    keyType = "PKCS12";289   } else if ("jck".equalsIgnoreCase(fileSuffix)) {290    keyType = "JCEKS";291   } else if ("pem".equalsIgnoreCase(fileSuffix) || "pkcs8".equalsIgnoreCase(fileSuffix)) {292    keyType = "PKCS8";293   } else if ("pkcs1".equalsIgnoreCase(fileSuffix)) {294    keyType = "PKCS1";295   } else if ("yljf".equalsIgnoreCase(fileSuffix)) {296    keyType = "yljf";297   } else if ("ldys".equalsIgnoreCase(fileSuffix)) {298    keyType = "ldys";299   } else{300    keyType = "JKS";301   }302 303   InputStream in = null;304   try {305    in = new FileInputStream(filePath);306    PrivateKey priKey = null;307    if ("JKS".equals(keyType) || "PKCS12".equals(keyType) || "JCEKS".equals(keyType)) {308     KeyStore ks = KeyStore.getInstance(keyType);309     if (password != null) {310      char[] cPasswd = password.toCharArray();311      ks.load(in, cPasswd);312      Enumeration<String> aliasenum = ks.aliases();313      String keyAlias = null;314      while (aliasenum.hasMoreElements()) {315       keyAlias = (String) aliasenum.nextElement();316       priKey = (PrivateKey) ks.getKey(keyAlias, cPasswd);317       if (priKey != null)318        break;319      }320     }321    }else if("yljf".equals(keyType)){322     BufferedReader br = new BufferedReader(new InputStreamReader(in));323     String s = br.readLine();324     PKCS8EncodedKeySpec priPKCS8=new PKCS8EncodedKeySpec(hexStrToBytes(s));325     KeyFactory keyf=KeyFactory.getInstance("RSA");326     PrivateKey myprikey=keyf.generatePrivate(priPKCS8);327     return myprikey;328    }else if("ldys".equals(keyType)){329     byte[] b = new byte[20480];330     in.read(b);331     PKCS8EncodedKeySpec priPKCS8=new PKCS8EncodedKeySpec(b);332     KeyFactory keyf=KeyFactory.getInstance("RSA");333     PrivateKey myprikey=keyf.generatePrivate(priPKCS8);334     return myprikey;335    }else {336     BufferedReader br = new BufferedReader(new InputStreamReader(in));337     StringBuilder sb = new StringBuilder();338     String readLine = null;339     while ((readLine = br.readLine()) != null) {340      if (readLine.charAt(0) == '-') {341       continue;342      } else {343       sb.append(readLine);344       sb.append('\r');345      }346     }347     if ("PKCS8".equals(keyType)) {348      PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decodeBase64(sb.toString()));349      KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);350      priKey = keyFactory.generatePrivate(priPKCS8);351     } else if ("PKCS1".equals(keyType)) {352 //     RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(sb.toString().getBytes()));353      RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(Base64.decodeBase64(sb.toString())));354      KeySpec rsaPrivKeySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(), asn1PrivKey.getPrivateExponent());355      KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);356      priKey = keyFactory.generatePrivate(rsaPrivKeySpec);357     }358    }359 360    return priKey;361   } catch (FileNotFoundException e) {362    throw new Exception("私钥路径文件不存在");363   } catch (KeyStoreException e) {364    throw new Exception("获取KeyStore对象异常");365   } catch (IOException e) {366    throw new Exception("读取私钥异常");367   } catch (NoSuchAlgorithmException e) {368    throw new Exception("生成私钥对象异常");369   } catch (CertificateException e) {370    throw new Exception("加载私钥密码异常");371   } catch (UnrecoverableKeyException e) {372    throw new Exception("生成私钥对象异常");373   } catch (InvalidKeySpecException e) {374    throw new Exception("生成私钥对象异常");375   } finally {376    try {377     if (in != null) {378      in.close();379     }380    } catch (IOException e) {381    }382   }383  }384 385  /**386   * RSA加密387   * 388   * @param plainBytes389   *   明文字节数组390   * @param publicKey391   *   公钥392   * @param keyLength393   *   密钥bit长度394   * @param reserveSize395   *   padding填充字节数,预留11字节396   * @param cipherAlgorithm397   *   加解密算法,一般为RSA/ECB/PKCS1Padding398   * @return 加密后字节数组,不经base64编码399   * @throws Exception400  */401  public static byte[] RSAEncrypt(byte[] plainBytes, PublicKey publicKey, int keyLength, int reserveSize, String cipherAlgorithm)402    throws Exception {403   int keyByteSize = keyLength / 8; // 密钥字节数404   int encryptBlockSize = keyByteSize - reserveSize; // 加密块大小=密钥字节数-padding填充字节数405   int nBlock = plainBytes.length / encryptBlockSize;// 计算分段加密的block数,向上取整406   if ((plainBytes.length % encryptBlockSize) != 0) { // 余数非0,block数再加1407    nBlock += 1;408   }409 410   try {411    Cipher cipher = Cipher.getInstance(cipherAlgorithm);412    cipher.init(Cipher.ENCRYPT_MODE, publicKey);413 414    // 输出buffer,大小为nBlock个keyByteSize415    ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * keyByteSize);416    // 分段加密417    for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) {418     int inputLen = plainBytes.length - offset;419     if (inputLen > encryptBlockSize) {420      inputLen = encryptBlockSize;421     }422 423     // 得到分段加密结果424     byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen);425     // 追加结果到输出buffer中426     outbuf.write(encryptedBlock);427    }428 429    outbuf.flush();430    outbuf.close();431    return outbuf.toByteArray();432   } catch (NoSuchAlgorithmException e) {433    throw new Exception(String.format("没有[%s]此类加密算法", cipherAlgorithm));434   } catch (NoSuchPaddingException e) {435    throw new Exception(String.format("没有[%s]此类填充模式", cipherAlgorithm));436   } catch (InvalidKeyException e) {437    throw new Exception("无效密钥");438   } catch (IllegalBlockSizeException e) {439    throw new Exception("加密块大小不合法");440   } catch (BadPaddingException e) {441    throw new Exception("错误填充模式");442   } catch (IOException e) {443    throw new Exception("字节输出流异常");444   }445  }446 447  /**448   * RSA解密449   * 450   * @param encryptedBytes451   *   加密后字节数组452   * @param privateKey453   *   私钥454   * @param keyLength455   *   密钥bit长度456   * @param reserveSize457   *   padding填充字节数,预留11字节458   * @param cipherAlgorithm459   *   加解密算法,一般为RSA/ECB/PKCS1Padding460   * @return 解密后字节数组,不经base64编码461   * @throws Exception462  */463  public static byte[] RSADecrypt(byte[] encryptedBytes, PrivateKey privateKey, int keyLength, int reserveSize, String cipherAlgorithm)464    throws Exception {465   int keyByteSize = keyLength / 8; // 密钥字节数466   int decryptBlockSize = keyByteSize - reserveSize; // 解密块大小=密钥字节数-padding填充字节数467   int nBlock = encryptedBytes.length / keyByteSize;// 计算分段解密的block数,理论上能整除468 469   try {470    Cipher cipher = Cipher.getInstance(cipherAlgorithm);471    cipher.init(Cipher.DECRYPT_MODE, privateKey);472 473    // 输出buffer,大小为nBlock个decryptBlockSize474    ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * decryptBlockSize);475    // 分段解密476    for (int offset = 0; offset < encryptedBytes.length; offset += keyByteSize) {477     // block大小: decryptBlock 或 剩余字节数478     int inputLen = encryptedBytes.length - offset;479     if (inputLen > keyByteSize) {480      inputLen = keyByteSize;481     }482 483     // 得到分段解密结果484     byte[] decryptedBlock = cipher.doFinal(encryptedBytes, offset, inputLen);485     // 追加结果到输出buffer中486     outbuf.write(decryptedBlock);487    }488 489    outbuf.flush();490    outbuf.close();491    return outbuf.toByteArray();492   } catch (NoSuchAlgorithmException e) {493    throw new Exception(String.format("没有[%s]此类解密算法", cipherAlgorithm));494   } catch (NoSuchPaddingException e) {495    throw new Exception(String.format("没有[%s]此类填充模式", cipherAlgorithm));496   } catch (InvalidKeyException e) {497    throw new Exception("无效密钥");498   } catch (IllegalBlockSizeException e) {499    throw new Exception("解密块大小不合法");500   } catch (BadPaddingException e) {501    throw new Exception("错误填充模式");502   } catch (IOException e) {503    throw new Exception("字节输出流异常");504   }505  }506 507  /**508   * AES加密509   * 510   * @param plainBytes511   *   明文字节数组512   * @param keyBytes513   *   密钥字节数组514   * @param keyAlgorithm515   *   密钥算法516   * @param cipherAlgorithm517   *   加解密算法518   * @param IV519   *   随机向量520   * @return 加密后字节数组,不经base64编码521   * @throws Exception522  */523  public static byte[] AESEncrypt(byte[] plainBytes, byte[] keyBytes, String keyAlgorithm, String cipherAlgorithm, String IV)524    throws Exception {525   try {526    // AES密钥长度为128bit、192bit、256bit,默认为128bit527    if (keyBytes.length % 8 != 0 || keyBytes.length < 16 || keyBytes.length > 32) {528     throw new Exception("AES密钥长度不合法");529    }530 531    Cipher cipher = Cipher.getInstance(cipherAlgorithm);532    SecretKey secretKey = new SecretKeySpec(keyBytes, keyAlgorithm);533    if (StringUtils.trimToNull(IV) != null) {534     IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes());535     cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);536    } else {537     cipher.init(Cipher.ENCRYPT_MODE, secretKey);538    }539 540    byte[] encryptedBytes = cipher.doFinal(plainBytes);541 542    return encryptedBytes;543   } catch (NoSuchAlgorithmException e) {544    throw new Exception(String.format("没有[%s]此类加密算法", cipherAlgorithm));545   } catch (NoSuchPaddingException e) {546    throw new Exception(String.format("没有[%s]此类填充模式", cipherAlgorithm));547   } catch (InvalidKeyException e) {548    throw new Exception("无效密钥");549   } catch (InvalidAlgorithmParameterException e) {550    throw new Exception("无效密钥参数");551   } catch (BadPaddingException e) {552    throw new Exception("错误填充模式");553   } catch (IllegalBlockSizeException e) {554    throw new Exception("加密块大小不合法");555   }556  }557 558  /**559   * AES解密560   * 561   * @param encryptedBytes562   *   密文字节数组,不经base64编码563   * @param keyBytes564   *   密钥字节数组565   * @param keyAlgorithm566   *   密钥算法567   * @param cipherAlgorithm568   *   加解密算法569   * @param IV570   *   随机向量571   * @return 解密后字节数组572   * @throws Exception573  */574  public static byte[] AESDecrypt(byte[] encryptedBytes, byte[] keyBytes, String keyAlgorithm, String cipherAlgorithm, String IV)575    throws Exception {576   try {577    // AES密钥长度为128bit、192bit、256bit,默认为128bit578    if (keyBytes.length % 8 != 0 || keyBytes.length < 16 || keyBytes.length > 32) {579     throw new Exception("AES密钥长度不合法");580    }581 582    Cipher cipher = Cipher.getInstance(cipherAlgorithm);583    SecretKey secretKey = new SecretKeySpec(keyBytes, keyAlgorithm);584    if (IV != null && StringUtils.trimToNull(IV) != null) {585     IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes());586     cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec);587    } else {588     cipher.init(Cipher.DECRYPT_MODE, secretKey);589    }590 591    byte[] decryptedBytes = cipher.doFinal(encryptedBytes);592 593    return decryptedBytes;594   } catch (NoSuchAlgorithmException e) {595    throw new Exception(String.format("没有[%s]此类加密算法", cipherAlgorithm));596   } catch (NoSuchPaddingException e) {597    throw new Exception(String.format("没有[%s]此类填充模式", cipherAlgorithm));598   } catch (InvalidKeyException e) {599    throw new Exception("无效密钥");600   } catch (InvalidAlgorithmParameterException e) {601    throw new Exception("无效密钥参数");602   } catch (BadPaddingException e) {603    throw new Exception("错误填充模式");604   } catch (IllegalBlockSizeException e) {605    throw new Exception("解密块大小不合法");606   }607  }608 609  public static void decode(String plain,String sign,String charset, PublicKey hzfPubKey) throws Exception{610   byte []signData = KeyUtil.string2bytes(sign, 16);611   byte[] signBytes = Base64.decodeBase64(signData);612   // 使用商户公钥验证签名613   boolean verifySign = CryptoUtil.verifyDigitalSign(plain.getBytes(charset), signBytes, hzfPubKey, "SHA1WithRSA");614   if (verifySign) {615    System.out.println("success");616   }else{617    System.out.println("failure");618   }619  }620  public static void decode2(String plain,String sign,String charset, PublicKey hzfPubKey) throws Exception{621   System.out.println(sign.length());622   byte[] signBytes = Base64.decodeBase64(sign.getBytes(charset));623   // 使用商户公钥验证签名624   boolean verifySign = CryptoUtil.verifyDigitalSign(plain.getBytes(charset), signBytes, hzfPubKey, "SHA1WithRSA");625   if (verifySign) {626    System.out.println("success");627   }else{628    System.out.println("failure");629   }630  }631  public static byte[] hexString2ByteArr(String hexStr) {632   return new BigInteger(hexStr, 16).toByteArray();633  }634  public static final byte[] hexStrToBytes(String s) {635   byte[] bytes; 636   bytes = new byte[s.length() / 2];637   for (int i = 0; i < bytes.length; i++) { 638    bytes[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 *   i + 2), 16);639   } 640   return bytes;641  }642  /**643   * 字符数组16进制字符644   * 645   * @param bytes646   * @return647  */648  public static String bytes2string(byte[] bytes, int radix) {649   int size = 2;650   if (radix == 2) {651    size = 8;652   }653   StringBuilder sb = new StringBuilder(bytes.length * size);654   for (int i = 0; i < bytes.length; i++) {655    int integer = bytes[i];656    while (integer < 0) {657     integer = integer + 256;658    }659    String str = Integer.toString(integer, radix);660    sb.append(StringUtils.leftPad(str.toUpperCase(), size, "0"));661   }662   return sb.toString();663  }664  665  public static void main(String[] args) throws Exception {666   PublicKey publicKey = null;667   PrivateKey privateKey = null;668   //获取私钥669   privateKey = CryptoUtil.getRSAPrivateKeyByFileSuffix("D://cert//private.pem","pem", null, "RSA");670   //获取公钥671   publicKey = CryptoUtil.getRSAPublicKeyByFileSuffix("D://cert//public.pem", "pem", "RSA");672   System.out.println("读取的私钥:"+privateKey);673   System.out.println("读取的公钥:"+publicKey);674  }675 }

控制台输出结果:

读取的私钥:sun.security.rsa.RSAPrivateCrtKeyImpl@fff05816读取的公钥:Sun RSA public key, 2048 bits modulus: 30352155361112247049303023420825968441063511556566487358373956485006944773551398257671324487561388937350982933590996006918917835477306783114880261383096591901729604794449957707356662262038622235714415672319014898606436696498375107689676577265348959122388532382235612467368418451329595782103970659911528392163885786170603134755166468968487939620387819720026031694626892021929646702745041404121725278045217747484135218828125738622519067039814579552154369394886130771836587225024718009130734917582986728907040272962770508323361317551681311374372344275619882074968240026190384773026535791888298002884088455001552303871327 public exponent: 65537
参考:  1  2、https://baike.baidu.com/item/%E6%95%B0%E5%AD%97%E8%AF%81%E4%B9%A6(百度百科,数字证书相关介绍,个人感觉挺好,挺详细的)

 

 

海外公司注册、海外银行开户、跨境平台代入驻、VAT、EPR等知识和在线办理:https://www.xlkjsw.com

原标题:常见数字证书类型

关键词:

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

可能感兴趣文章

我的浏览记录