有人可以帮助我使用 BouncyCastle 实现扩展主题备用名称吗?
Can somebody help me to implement extension Subject Alternative Names using BouncyCastle?
我有一些字符串,用逗号分隔。我必须添加与 Subject Alternative Names 扩展名的任何 GeneralName 匹配的所有扩展名。有人可以帮我完成 for 循环吗?
@Override
public boolean saveKeypair(String arg0) {
KeyPair keyPair = generateKeyPair(Integer.parseInt(access.getPublicKeyParameter()));
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
X500Name name = new X500Name(access.getSubject());
BigInteger serial = new BigInteger(access.getSerialNumber());
Date notBefore = access.getNotBefore();
Date notAfter = access.getNotAfter();
X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(name, serial, notBefore, notAfter, name,
publicKey);
// BEGIN extensions
// certificate policies
boolean isCritPol = access.isCritical(3);
PolicyInformation[] policies = new PolicyInformation[1];
policies[0] = new PolicyInformation(new ASN1ObjectIdentifier("2.16.840.1.101.2.1.11.5"),
new DERSequence(new PolicyQualifierInfo(access.getCpsUri())));
try {
certBuilder.addExtension(Extension.certificatePolicies, isCritPol, new CertificatePolicies(policies));
} catch (CertIOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// END CP
// subject alternative name
List<GeneralName> altNames = new ArrayList<GeneralName>();
String [] altSubNames = access.getAlternativeName(5);
for(String altName : altSubNames){
// I NEED THIS LOOP, AND I DON'T KNOW HOW TO DO IT
}
// END SAN
// END extensions
try {
// Content Signer
Security.addProvider(new BouncyCastleProvider());
ContentSigner sigGen = new JcaContentSignerBuilder(signatureAlgorithm).setProvider(providerName)
.build(privateKey);
// Certificate
X509Certificate certificate = new JcaX509CertificateConverter().setProvider(providerName)
.getCertificate(certBuilder.build(sigGen));
certificate.verify(publicKey);
X509Certificate[] chain = new X509Certificate[1];
chain[0] = certificate;
keyStore.setKeyEntry(arg0, privateKey, password.toCharArray(), chain);
} catch (OperatorCreationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CertificateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SignatureException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
// BEGIN of functions for saveKeypair
public KeyPair generateKeyPair(int keySize) {
KeyPair keyPair = null;
try {
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(algorithm);
keyGenerator.initialize(keySize);
keyPair = keyGenerator.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return keyPair;
}
// END of functions for saveKeypair
该功能的其余部分正在运行。
我在 Java 中使用 BouncyCastle。 altSubName
是一些字符串的数组。并且应该以某种方式检查这些字符串是 SubjectAlternativeName 中的哪一个,并且应该添加包含所有通用名称的扩展名。
根据 RFC 5280,主题备用名称 扩展的某些字段具有已定义的格式:
等等(看看RFC 5280link,很详细)
因此,要了解每个 String
对应的字段是什么,您必须检查它们是否具有在每个字段中定义的格式。
对于 rfc822Name
我发现了这个怪物正则表达式:
String rfc822Regex = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])";
String s = "test_ad.fade@mail.com";
if (s.matches(rfc822Regex)) {
// is valid email
}
对于其他字段,您可以搜索每种特定格式的正则表达式。我认为唯一的问题是 otherName
字段,因为它可以有 any 格式(必须为每个证书颁发机构指定):
OtherName ::= SEQUENCE {
type-id OBJECT IDENTIFIER,
value [0] EXPLICIT ANY DEFINED BY type-id }
无论如何,通用代码将是这样的(假设您已经搜索了如何验证每种特定格式):
// check the format and add with the correct field type
if (isValidEmail(altName)) {
altNames.add(new GeneralName(GeneralName.rfc822Name, "user@mail.com"));
} else if (isValidDnsName(altName)) {
altNames.add(new GeneralName(GeneralName.dNSName, "test.com"));
} else if (isValidIpAddress(altName)) {
altNames.add(new GeneralName(GeneralName.iPAddress, "127.0.0.1"));
}
// ... and so on, for all GeneralName types
然后将扩展名添加到 certBuilder
:
GeneralNames subjectAltNames = GeneralNames.getInstance(new DERSequence((GeneralName[]) altNames.toArray(new GeneralName[] {})));
certBuilder.addExtension(Extension.subjectAlternativeName, false, subjectAltNames);
我有一些字符串,用逗号分隔。我必须添加与 Subject Alternative Names 扩展名的任何 GeneralName 匹配的所有扩展名。有人可以帮我完成 for 循环吗?
@Override
public boolean saveKeypair(String arg0) {
KeyPair keyPair = generateKeyPair(Integer.parseInt(access.getPublicKeyParameter()));
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
X500Name name = new X500Name(access.getSubject());
BigInteger serial = new BigInteger(access.getSerialNumber());
Date notBefore = access.getNotBefore();
Date notAfter = access.getNotAfter();
X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(name, serial, notBefore, notAfter, name,
publicKey);
// BEGIN extensions
// certificate policies
boolean isCritPol = access.isCritical(3);
PolicyInformation[] policies = new PolicyInformation[1];
policies[0] = new PolicyInformation(new ASN1ObjectIdentifier("2.16.840.1.101.2.1.11.5"),
new DERSequence(new PolicyQualifierInfo(access.getCpsUri())));
try {
certBuilder.addExtension(Extension.certificatePolicies, isCritPol, new CertificatePolicies(policies));
} catch (CertIOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// END CP
// subject alternative name
List<GeneralName> altNames = new ArrayList<GeneralName>();
String [] altSubNames = access.getAlternativeName(5);
for(String altName : altSubNames){
// I NEED THIS LOOP, AND I DON'T KNOW HOW TO DO IT
}
// END SAN
// END extensions
try {
// Content Signer
Security.addProvider(new BouncyCastleProvider());
ContentSigner sigGen = new JcaContentSignerBuilder(signatureAlgorithm).setProvider(providerName)
.build(privateKey);
// Certificate
X509Certificate certificate = new JcaX509CertificateConverter().setProvider(providerName)
.getCertificate(certBuilder.build(sigGen));
certificate.verify(publicKey);
X509Certificate[] chain = new X509Certificate[1];
chain[0] = certificate;
keyStore.setKeyEntry(arg0, privateKey, password.toCharArray(), chain);
} catch (OperatorCreationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CertificateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SignatureException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
// BEGIN of functions for saveKeypair
public KeyPair generateKeyPair(int keySize) {
KeyPair keyPair = null;
try {
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(algorithm);
keyGenerator.initialize(keySize);
keyPair = keyGenerator.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return keyPair;
}
// END of functions for saveKeypair
该功能的其余部分正在运行。
我在 Java 中使用 BouncyCastle。 altSubName
是一些字符串的数组。并且应该以某种方式检查这些字符串是 SubjectAlternativeName 中的哪一个,并且应该添加包含所有通用名称的扩展名。
根据 RFC 5280,主题备用名称 扩展的某些字段具有已定义的格式:
等等(看看RFC 5280link,很详细)
因此,要了解每个 String
对应的字段是什么,您必须检查它们是否具有在每个字段中定义的格式。
对于 rfc822Name
我发现了这个怪物正则表达式:
String rfc822Regex = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])";
String s = "test_ad.fade@mail.com";
if (s.matches(rfc822Regex)) {
// is valid email
}
对于其他字段,您可以搜索每种特定格式的正则表达式。我认为唯一的问题是 otherName
字段,因为它可以有 any 格式(必须为每个证书颁发机构指定):
OtherName ::= SEQUENCE {
type-id OBJECT IDENTIFIER,
value [0] EXPLICIT ANY DEFINED BY type-id }
无论如何,通用代码将是这样的(假设您已经搜索了如何验证每种特定格式):
// check the format and add with the correct field type
if (isValidEmail(altName)) {
altNames.add(new GeneralName(GeneralName.rfc822Name, "user@mail.com"));
} else if (isValidDnsName(altName)) {
altNames.add(new GeneralName(GeneralName.dNSName, "test.com"));
} else if (isValidIpAddress(altName)) {
altNames.add(new GeneralName(GeneralName.iPAddress, "127.0.0.1"));
}
// ... and so on, for all GeneralName types
然后将扩展名添加到 certBuilder
:
GeneralNames subjectAltNames = GeneralNames.getInstance(new DERSequence((GeneralName[]) altNames.toArray(new GeneralName[] {})));
certBuilder.addExtension(Extension.subjectAlternativeName, false, subjectAltNames);