SSL证书结构
结构图
SSL_ctf_struct.jpgSSL证书包括两部分,证书信息和签名信息,签名信息在证书合法性形校验使用。
根证书生成
根证书生成过程-2.jpg根证书的生成分为三个部分:
- 生成根证书的公钥和私钥
- 构建证书的原始证书,包括公钥、加密算法、生效时间、过期时间等信息。
- 用根证书私钥对原始证书进行签名,生成合法的根证书。
- 根证书安装,将根证书安装到客户端,比如手机、电脑中。
代码
//生成证书
public static KeyStore createRootCertificate(Authority authority,
String keyStoreType) throws NoSuchAlgorithmException,
NoSuchProviderException, IOException,
OperatorCreationException, CertificateException, KeyStoreException {
//生成公钥和私钥
KeyPair keyPair = generateKeyPair(ROOT_KEYSIZE);
//生成证书
X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE);
nameBuilder.addRDN(BCStyle.CN, authority.commonName());
nameBuilder.addRDN(BCStyle.O, authority.organization());
nameBuilder.addRDN(BCStyle.OU, authority.organizationalUnitName());
X500Name issuer = nameBuilder.build();
BigInteger serial = BigInteger.valueOf(initRandomSerial());
X500Name subject = issuer;
PublicKey pubKey = keyPair.getPublic();
X509v3CertificateBuilder generator = new JcaX509v3CertificateBuilder(
issuer, serial, NOT_BEFORE, NOT_AFTER, subject, pubKey);
generator.addExtension(Extension.subjectKeyIdentifier, false,
createSubjectKeyIdentifier(pubKey));
generator.addExtension(Extension.basicConstraints, true,
new BasicConstraints(true));
KeyUsage usage = new KeyUsage(KeyUsage.keyCertSign
| KeyUsage.digitalSignature | KeyUsage.keyEncipherment
| KeyUsage.dataEncipherment | KeyUsage.cRLSign);
generator.addExtension(Extension.keyUsage, false, usage);
ASN1EncodableVector purposes = new ASN1EncodableVector();
purposes.add(KeyPurposeId.id_kp_serverAuth);
purposes.add(KeyPurposeId.id_kp_clientAuth);
purposes.add(KeyPurposeId.anyExtendedKeyUsage);
generator.addExtension(Extension.extendedKeyUsage, false,
new DERSequence(purposes));
X509Certificate cert = signCertificate(generator, keyPair.getPrivate());
KeyStore result = KeyStore
.getInstance(keyStoreType/* , PROVIDER_NAME */);
result.load(null, null);
result.setKeyEntry(authority.alias(), keyPair.getPrivate(),
authority.password(), new Certificate[] { cert });
return result;
}
服务器证书生成
服务器证书生成过程.jpg服务器证书的生成过程与根证书类似,只是给服务器原始证书签名的不是自己生成的私钥,而是根证书的私钥。
public static KeyStore createServerCertificate(String commonName,
SubjectAlternativeNameHolder subjectAlternativeNames,
Authority authority, Certificate caCert, PrivateKey caPrivKey)
throws NoSuchAlgorithmException, NoSuchProviderException,
IOException, OperatorCreationException, CertificateException,
InvalidKeyException, SignatureException, KeyStoreException {
KeyPair keyPair = generateKeyPair(FAKE_KEYSIZE);
X500Name issuer = new X509CertificateHolder(caCert.getEncoded())
.getSubject();
BigInteger serial = BigInteger.valueOf(initRandomSerial());
X500NameBuilder name = new X500NameBuilder(BCStyle.INSTANCE);
name.addRDN(BCStyle.CN, commonName);
name.addRDN(BCStyle.O, authority.certOrganisation());
name.addRDN(BCStyle.OU, authority.certOrganizationalUnitName());
X500Name subject = name.build();
X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(issuer, serial, NOT_BEFORE,
new Date(System.currentTimeMillis() + ONE_DAY), subject, keyPair.getPublic());
builder.addExtension(Extension.subjectKeyIdentifier, false,
createSubjectKeyIdentifier(keyPair.getPublic()));
builder.addExtension(Extension.basicConstraints, false,
new BasicConstraints(false));
subjectAlternativeNames.fillInto(builder);
X509Certificate cert = signCertificate(builder, caPrivKey);
cert.checkValidity(new Date());
cert.verify(caCert.getPublicKey());
KeyStore result = KeyStore.getInstance(KeyStore.getDefaultType()
/* , PROVIDER_NAME */);
result.load(null, null);
Certificate[] chain = { cert, caCert };
result.setKeyEntry(authority.alias(), keyPair.getPrivate(),
authority.password(), chain);
return result;
}
客户端证书校验过程
- 客户端收到服务端发送的服务器SSL证书。
- 解析获得服务器证书的颁发者
- 找到已安装在客户端的颁发者根证书,如果没找到则服务器证书非法,停止校验。
- 用根证书的公钥解析服务器证书的签名信息,完成解析认证成功,否则失败。
网友评论