Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.

Commit edcf09c

Browse files
committed
Add subject alt names to CSR when local generated
Fix defaults for keyType, keyLength, keyCurve, signatureAlgorithm
1 parent 60a8bc5 commit edcf09c

8 files changed

Lines changed: 85 additions & 58 deletions

File tree

src/main/java/com/venafi/vcert/sdk/SignatureAlgorithm.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ public enum SignatureAlgorithm {
66

77
UnknownSignatureAlgorithm(""),
88
MD2withRSA("MD2withRSA"),
9-
109
MD5WithRSA("MD5withRSA"),
1110
SHA1WithRSA("SHA1withRSA"),
1211
SHA256WithRSA("SHA256withRSA"),

src/main/java/com/venafi/vcert/sdk/certificate/CertificateRequest.java

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@
1010
import org.bouncycastle.asn1.x500.style.BCStyle;
1111
import org.bouncycastle.jce.PKCS10CertificationRequest;
1212
import org.bouncycastle.util.io.pem.PemReader;
13-
import java.util.Base64;
13+
import org.bouncycastle.asn1.x509.GeneralName;
14+
import org.bouncycastle.asn1.x509.GeneralNames;
15+
import org.bouncycastle.asn1.x509.X509Extension;
16+
import org.bouncycastle.asn1.x509.X509Extensions;
17+
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
18+
import org.bouncycastle.asn1.pkcs.Attribute;
19+
import org.bouncycastle.asn1.DEROctetString;
20+
import org.bouncycastle.asn1.DERSet;
1421

1522
import javax.security.auth.x500.X500Principal;
1623
import java.io.ByteArrayOutputStream;
@@ -25,6 +32,9 @@
2532
import java.util.Collection;
2633
import java.util.List;
2734
import java.util.Objects;
35+
import java.util.ArrayList;
36+
import java.util.Vector;
37+
import java.util.Base64;
2838

2939
import static java.lang.String.format;
3040
import static java.time.temporal.ChronoUnit.MINUTES;
@@ -95,17 +105,42 @@ public void generatePrivateKey() throws VCertException {
95105

96106
public void generateCSR() throws VCertException {
97107
try {
108+
List<GeneralName> sans = new ArrayList<GeneralName>();
109+
110+
for ( String san : dnsNames ) {
111+
sans.add(new GeneralName(GeneralName.dNSName, san));
112+
}
113+
114+
for ( InetAddress san : ipAddresses ) {
115+
sans.add(new GeneralName(GeneralName.iPAddress, new DEROctetString(san.getAddress())));
116+
}
117+
118+
for ( String san : emailAddresses ) {
119+
sans.add(new GeneralName(GeneralName.rfc822Name, san));
120+
}
121+
122+
GeneralNames names = new GeneralNames(sans.toArray(new GeneralName[] {}));
123+
Vector oids = new Vector();
124+
Vector values = new Vector();
125+
126+
oids.add(X509Extensions.SubjectAlternativeName);
127+
values.add(new X509Extension(false, new DEROctetString(names)));
128+
129+
X509Extensions extensions = new X509Extensions(oids, values);
130+
Attribute attribute = new Attribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, new DERSet(extensions));
131+
98132
PKCS10CertificationRequest certificationRequest = new PKCS10CertificationRequest(
99133
signatureAlgorithm.standardName(),
100134
subject.toX500Principal(),
101135
keyPair.getPublic(),
102-
null,
136+
new DERSet(attribute),
103137
keyPair.getPrivate());
104138

105139
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
106140
outputStream.write("-----BEGIN CERTIFICATE REQUEST-----".getBytes());
107141
outputStream.write(System.lineSeparator().getBytes());
108-
outputStream.write(Base64.getEncoder().encode(certificationRequest.getEncoded()));
142+
outputStream.write(Base64.getMimeEncoder().encode(certificationRequest.getEncoded()));
143+
outputStream.write(System.lineSeparator().getBytes());
109144
outputStream.write("-----END CERTIFICATE REQUEST-----".getBytes());
110145
csr = outputStream.toByteArray();
111146
} catch(Exception e) {

src/main/java/com/venafi/vcert/sdk/certificate/PublicKeyAlgorithm.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ public enum PublicKeyAlgorithm {
44
Unknown,
55
RSA,
66
DSA,
7-
ECDSA
7+
ECDSA,
8+
EC
89
}

src/main/java/com/venafi/vcert/sdk/connectors/ServerPolicy.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ public Policy toPolicy() {
145145
public ZoneConfiguration toZoneConfig() {
146146
return new ZoneConfiguration()
147147
.customAttributeValues(new HashMap<>())
148-
.hashAlgorithm(SignatureAlgorithm.MD2withRSA)
149148
.country(subject.country().value())
150149
.organization(subject.organization().value())
151150
.organizationalUnit(subject.organizationalUnit().values())

src/main/java/com/venafi/vcert/sdk/connectors/cloud/CloudConnector.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public CertificateRequest generateRequest(ZoneConfiguration config, CertificateR
103103
request.csr(null);
104104
break;
105105
default:
106-
throw new VCertException(format("Unreconginised request CSR origin %s", request.csrOrigin()));
106+
throw new VCertException(format("Unrecognized request CSR origin %s", request.csrOrigin()));
107107
}
108108

109109
return request;
@@ -118,7 +118,7 @@ public String requestCertificate(CertificateRequest request, String zone) throws
118118
throw new VCertException("service generated CSR is not supported by Saas service");
119119
}
120120
if (user == null || user.company() == null) {
121-
throw new VCertException("Must be autheticated to request a certificate");
121+
throw new VCertException("Must be authenticated to request a certificate");
122122
}
123123
Zone z = getZoneByTag(zone);
124124
CertificateRequestsResponse response = cloud.certificateRequest(
@@ -141,7 +141,7 @@ public PEMCollection retrieveCertificate(CertificateRequest request) throws VCer
141141
String certificateRequestId = null;
142142
Cloud.CertificateSearchResponse certificateSearchResponse = searchCertificatesByFingerprint(request.thumbprint());
143143
if(certificateSearchResponse.certificates().size() == 0) {
144-
throw new VCertException(format("No certifiate found using fingerprint %s", request.thumbprint()));
144+
throw new VCertException(format("No certificate found using fingerprint %s", request.thumbprint()));
145145
}
146146

147147
List<String> reqIds = new ArrayList<>();
@@ -195,7 +195,7 @@ public PEMCollection retrieveCertificate(CertificateRequest request) throws VCer
195195
}
196196

197197
if(user == null || user.company() == null) {
198-
throw new VCertException("Must be autheticated to retieve certificate");
198+
throw new VCertException("Must be authenticated to retieve certificate");
199199
}
200200

201201
if(isNotBlank(request.pickupId())) {

src/main/java/com/venafi/vcert/sdk/connectors/tpp/Tpp.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ class CertificateSearchResponse {
8282

8383
@Data
8484
class Certificate {
85-
8685
@SerializedName("DN") private String certificateRequestId;
8786
}
8887

src/main/java/com/venafi/vcert/sdk/connectors/tpp/TppConnector.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.concurrent.TimeUnit;
2323
import java.util.regex.Matcher;
2424
import java.util.regex.Pattern;
25+
import java.net.InetAddress;
2526

2627
import static java.lang.String.format;
2728
import static java.time.Duration.ZERO;
@@ -134,7 +135,6 @@ public CertificateRequest generateRequest(ZoneConfiguration config, CertificateR
134135
if("0".equals(config.customAttributeValues().get(tppAttributeManualCSR))) {
135136
throw new VCertException("Unable to request certificate with user provided CSR when zone configuration is 'Manual Csr' = 0");
136137
}
137-
request.generatePrivateKey();
138138
if(Is.blank(request.csr())) {
139139
throw new VCertException("CSR was supposed to be provided by user, but it's empty");
140140
}
@@ -164,11 +164,18 @@ private CertificateRequestsPayload prepareRequest(CertificateRequest request, St
164164
CertificateRequestsPayload payload;
165165
switch(request.csrOrigin()) {
166166
case LocalGeneratedCSR:
167+
payload = new CertificateRequestsPayload()
168+
.policyDN(getPolicyDN(zone))
169+
.pkcs10(new String(request.csr()))
170+
.objectName(request.friendlyName())
171+
.disableAutomaticRenewal(true);
172+
break;
167173
case UserProvidedCSR:
168174
payload = new CertificateRequestsPayload()
169175
.policyDN(getPolicyDN(zone))
170176
.pkcs10(new String(request.csr()))
171177
.objectName(request.friendlyName())
178+
.subjectAltNames(wrapAltNames(request))
172179
.disableAutomaticRenewal(true);
173180
break;
174181
case ServiceGeneratedCSR:
@@ -191,7 +198,7 @@ private CertificateRequestsPayload prepareRequest(CertificateRequest request, St
191198
}
192199
case ECDSA: {
193200
payload.keyAlgorithm("ECC");
194-
payload.ellipticCurve(request.keyCurve().name());
201+
payload.ellipticCurve(request.keyCurve().value());
195202
break;
196203
}
197204
}
@@ -212,7 +219,7 @@ private List<SANItem> toSanItems(Collection<?> collection, int type) {
212219
.orElse(Collections.emptyList())
213220
.stream()
214221
.filter(Objects::nonNull)
215-
.map(entry -> new SANItem().type(type).name(entry.toString()))
222+
.map(entry -> new SANItem().type(type).name( type == 7 ? ((InetAddress)entry).getHostAddress() : entry.toString()) )
216223
.collect(toList());
217224
}
218225

@@ -224,7 +231,7 @@ public PEMCollection retrieveCertificate(CertificateRequest request) throws VCer
224231
if(isNotBlank(request.pickupId()) && isNotBlank(request.thumbprint())) {
225232
Tpp.CertificateSearchResponse searchResult = searchCertificatesByFingerprint(request.thumbprint());
226233
if(searchResult.certificates().size() == 0) {
227-
throw new VCertException(format("No certifiate found using fingerprint %s", request.thumbprint()));
234+
throw new VCertException(format("No certificate found using fingerprint %s", request.thumbprint()));
228235
}
229236
if(searchResult.certificates().size() > 1) {
230237
throw new VCertException(format("Error: more than one CertificateRequestId was found with the same thumbprint %s", request.thumbprint()));
@@ -418,6 +425,7 @@ static class CertificateRequestsPayload {
418425
private String city;
419426
private String state;
420427
private String country;
428+
@SerializedName("SubjectAltNames")
421429
private Collection<SANItem> subjectAltNames;
422430
private String contact;
423431
@SerializedName("CASpecificAttributes")

src/main/java/com/venafi/vcert/sdk/connectors/tpp/ZoneConfiguration.java

Lines changed: 29 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,42 @@ public void updateCertificateRequest(CertificateRequest request) {
4545
subject.country(Entity.of(subject.country(), country).resolve());
4646
subject.province(Entity.of(subject.province(), province).resolve());
4747
subject.locality(Entity.of(subject.locality(), locality).resolve());
48-
if(hashAlgorithm != SignatureAlgorithm.UnknownSignatureAlgorithm) {
49-
request.signatureAlgorithm(hashAlgorithm);
50-
} else {
51-
request.signatureAlgorithm(SignatureAlgorithm.SHA256WithRSA);
48+
49+
// apply defaults for settings that weren't specified and then make sure they comply with policy
50+
if (request.keyType() == null) {
51+
request.keyType(KeyType.defaultKeyType());
52+
}
53+
54+
switch (request.keyType())
55+
{
56+
case ECDSA:
57+
if (request.keyCurve() == null) {
58+
request.keyCurve(EllipticCurve.ellipticCurveDefault());
59+
}
60+
if (request.signatureAlgorithm() == SignatureAlgorithm.UnknownSignatureAlgorithm) {
61+
request.signatureAlgorithm(SignatureAlgorithm.ECDSAWithSHA256);
62+
}
63+
break;
64+
65+
default:
66+
if (request.keyLength() < 2048) {
67+
request.keyLength(2048);
68+
}
69+
if (request.signatureAlgorithm() == SignatureAlgorithm.UnknownSignatureAlgorithm) {
70+
request.signatureAlgorithm(SignatureAlgorithm.SHA256WithRSA);
71+
}
72+
break;
5273
}
5374

5475
if(!Is.blank(policy.allowedKeyConfigurations())) {
55-
boolean foundMatch = false;
5676
for(AllowedKeyConfiguration keyConf : policy.allowedKeyConfigurations()) {
5777
if(keyConf.keyType() == request.keyType()) {
58-
foundMatch = true;
5978
switch (request.keyType()) {
6079
case ECDSA: {
6180
if(!Is.blank(keyConf.keyCurves())) {
62-
request.keyCurve(keyConf.keyCurves().get(0));
63-
} else {
64-
request.keyCurve(EllipticCurve.ellipticCurveDefault());
81+
if (!keyConf.keyCurves().contains(request.keyCurve())) {
82+
request.keyCurve(keyConf.keyCurves().get(0));
83+
}
6584
}
6685
break;
6786
}
@@ -74,47 +93,14 @@ public void updateCertificateRequest(CertificateRequest request) {
7493
}
7594
}
7695
if(!sizeOK) {
77-
List<Integer> reversedKeySizes = new ArrayList<>(keyConf.keySizes()); // not reversing the original
78-
reversedKeySizes.sort(Collections.reverseOrder());
79-
request.keyLength(reversedKeySizes.get(0));
96+
request.keyLength(keyConf.keySizes().get(0));
8097
}
81-
} else {
82-
request.keyLength(keyConf.keySizes().get(0));
8398
}
8499
break;
85100
}
86101
}
87102
}
88103
}
89-
if(!foundMatch) {
90-
AllowedKeyConfiguration configuration = policy.allowedKeyConfigurations().get(0);
91-
request.keyType(configuration.keyType());
92-
switch (request.keyType()) {
93-
case ECDSA: {
94-
if(!Is.blank(configuration.keyCurves())) {
95-
request.keyCurve(configuration.keyCurves().get(0));
96-
} else {
97-
request.keyCurve(EllipticCurve.ellipticCurveDefault());
98-
}
99-
break;
100-
}
101-
case RSA: {
102-
if(!Is.blank(configuration.keySizes())) {
103-
List<Integer> reversedKeySizes = new ArrayList<>(configuration.keySizes());
104-
reversedKeySizes.sort(Comparator.reverseOrder());
105-
request.keyLength(reversedKeySizes.get(0));
106-
} else {
107-
request.keyLength(2048);
108-
}
109-
break;
110-
}
111-
}
112-
}
113-
} else {
114-
// Zone config has no key length parameters, so we just pass user's -key-size or fall to default 2048
115-
if(KeyType.RSA.equals(request.keyType()) && request.keyLength() == 0) {
116-
request.keyLength(2048);
117-
}
118104
}
119105
}
120106

0 commit comments

Comments
 (0)