Java密码学

来源:互联网 发布:gta5捏脸数据女韩国 编辑:程序博客网 时间:2024/06/05 04:15

自证书

自证书 , 就是自己办法给自己 (我是国王, 我说我没错就没错!!)

sun.security.x509的自签名

CertAndKeyGen gen = new CertAndKeyGen("RSA", "SHA1WithRSA");gen.generate(1024);//generate private key for sign certX509Certificate cert = gen.getSelfCertificate(new X500Name("CN=caliburn"), (long) 50 * 365 * 24 * 3600);
  1. 这里CertAndKeyGen包含了KeyPairGenerator类, 也就是, 之类有生成公钥和私钥的算法
  2. 第三行参数 : 公共名称 (CN) , 有效时间

https://www.ibm.com/support/knowledgecenter/zh/SSZPE3_9.1.2/Platform/SSL_1/SSL_1_About_SSL_certs.html

CN值, 用于匹配, 客户端登陆的是不是CA发的证书的网站

非自证书 (签名证书)

也就是要去CA那里申请, 需要发个request, 如何构造request

client端

GenerateKeys gk = new GenerateKeys(1024);//构造公钥和私钥PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(      new X500Principal("CN=Requested Test Certificate"), gk.getPublicKey());//CN和公钥JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder("SHA256withRSA");//签名算法ContentSigner signer = csBuilder.build(gk.getPrivateKey());//私钥签名PKCS10CertificationRequest csr = p10Builder.build(signer);

这里生成的私钥要自己保存好, 放到keystore也好, 生成一个文件也好

CA端 (sever端):

PKCS10CertificationRequest csr = ...;//获取申请/*获取CA端的自证书, 用于构造信息, 这里需要注意, 我们要构造的是BC的X.509证书, 因为这个代码环境都是BC, 用java.security的证书类是不能操作的*/CertificateFactory certFactory = CertificateFactory.getInstance("X.509");        X509Certificate cacert = (X509Certificate) certFactory.generateCertificate(                FileUtils.openInputStream(new File("project/4d/sever/rootcer.pem")));//一大堆参数 ,填充到生成器里AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA");        AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);        org.bouncycastle.asn1.x500.X500Name issuer = new org.bouncycastle.asn1.x500.X500Name(cacert.getSubjectX500Principal().getName());        BigInteger serial = new BigInteger(32, new SecureRandom());        Date from = new Date();        Date to = new Date(System.currentTimeMillis() + (365 * 80 * 86400000L));        DigestCalculator digCalc = new BcDigestCalculatorProvider().get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1));        X509v3CertificateBuilder certgen = new X509v3CertificateBuilder(issuer, serial, from, to, csr.getSubject(), csr.getSubjectPublicKeyInfo());        //CA端进行签名, 才有具有法律效力        ContentSigner signer = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(PrivateKeyFactory.createKey(CA的私钥.getEncoded()));        //生成BC结构的证书        Security.addProvider(new BouncyCastleProvider());        X509Certificate bc = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certgen.build(signer));        //最终生成的是java.security的证书

我国使用的是双证书, 也就是我们还要弄一个加密证书.
过程

  1. 生成公钥A和私钥A
  2. 从request|刚刚生成签名证书里取相关信息( 公钥B和其他信息 )
  3. 生成对称加密C , 加密私钥A
  4. 公钥B加密该对称加密C
  5. 放进一个自定义的协议ASN1Object

这里主要讲讲, 如何从request里获取公钥

先看request的ASN结构

RFC 2986 - PKCS #10: Certification Request Syntax

   CertificationRequestInfo ::= SEQUENCE {        version       INTEGER { v1(0) } (v1,...),        subject       Name,        subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},        attributes    [0] Attributes{{ CRIAttributes }}   }   SubjectPublicKeyInfo { ALGORITHM : IOSet} ::= SEQUENCE {        algorithm        AlgorithmIdentifier {{IOSet}},        subjectPublicKey BIT STRING   }

X.509格式则为 (X.509为证书公钥的结构)

 SubjectPublicKeyInfo ::= SEQUENCE {   algorithm AlgorithmIdentifier,   subjectPublicKey BIT STRING }

于是乎, 我们就明白编码结构为X.509 (除此以为, 还有PKCS#1结构, 该结构对应的是AlgorithmIdentifier, 可以通过该结构, 将X.509转换成PKCS#1)

所以,我们先获取该结构的字节码, 在转换成X509, 最后通过工厂类进行操作即可

PKCS10CertificationRequest csr=...;X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(csr.getSubjectPublicKeyInfo().toASN1Primitive().getEncoded());PublicKey Signedpk =KeyFactory.getInstance("RSA").generatePublic(x509EncodedKeySpec);

笔者之前也说过, JCA(这里是BC)和JCE(Java自身的)之前的转换, 是通过Jca开头的类来转换

PKCS10CertificationRequest csr=...;JcaPKCS10CertificationRequest jcaPKCS10CertificationRequest = new JcaPKCS10CertificationRequest(csr);PublicKey Signedpk = jcaPKCS10CertificationRequest.getPublicKey();

番外

也可以通过转换成PKCS#1的结构, 再进行提取(不建议, 与其他代码不融洽)

PKCS10CertificationRequest csr=...RSAKeyParameters rsa = (RSAKeyParameters) PublicKeyFactory.createKey(csr.getSubjectPublicKeyInfo());RSAPublicKeySpec rsaSpec = new RSAPublicKeySpec(rsa.getModulus(), rsa.getExponent());PublicKey Signedpk = KeyFactory.getInstance("RSA").generatePublic(rsaSpec);
原创粉丝点击