On Tue, 3 Jun 2025 15:31:37 GMT, Sean Mullan <mul...@openjdk.org> wrote:

>> I think the way it currently is follows the builder pattern better. All of 
>> the 'set' methods return `this` which means if I change this method to a 
>> constructor, I'd have to duplicate the "set" code from all those methods.
>> 
>> I like the idea of using `Duration` but the API for it doesn't really lend 
>> itself to this use case. When the certificate is finally created, we write 
>> `Date` objects to the DerOutputStream so I'd have to choose a start time and 
>> then calculate the end time based on the duration. It's not hard, but it 
>> doesn't seem worth it when the common use case of this class is to generate 
>> short-lived certificates for a test. The default one-hour validity will 
>> cover the vast majority of tests.
>
>> I think the way it currently is follows the builder pattern better. All of 
>> the 'set' methods return `this` which means if I change this method to a 
>> constructor, I'd have to duplicate the "set" code from all those methods.
> 
> I'm not sure what you mean - can you give an example? I don't see any 
> advantages of using a static method here, but I agree it works either way.
> 
>> I like the idea of using `Duration` but the API for it doesn't really lend 
>> itself to this use case. When the certificate is finally created, we write 
>> `Date` objects to the DerOutputStream so I'd have to choose a start time and 
>> then calculate the end time based on the duration. It's not hard, but it 
>> doesn't seem worth it when the common use case of this class is to generate 
>> short-lived certificates for a test. The default one-hour validity will 
>> cover the vast majority of tests.
> 
> I view this test utility class as being flexible enough for different cases. 
> This is a useful method in that the other parameters are common fields that 
> all certs usually have but it also means I can't use this method to to create 
> a certificate with a longer, or shorter validity period. Alternatively, how 
> about adding another method that hard-codes it as one hour:
> 
> `CertificateBuilder oneHourValidity()`

As a constructor, the code would look like this


public CertificateBuilder(String subjectName,
                              PublicKey publicKey, PublicKey caKey, KeyUsage... 
keyUsages)
            throws CertificateException, IOException {
        factory = CertificateFactory.getInstance("X.509");
        SecureRandom random = new SecureRandom();

        boolean [] keyUsage = new boolean[KeyUsage.values().length];
        for (KeyUsage ku : keyUsages) {
            keyUsage[ku.ordinal()] = true;
        }

        this.subjectName = new X500Principal(subjectName);
        this.publicKey = Objects.requireNonNull(publicKey, "Caught null public 
key");
        notBefore = (Date)Date.from(Instant.now().minus(1, ChronoUnit.HOURS));
        notAfter = Date.from(Instant.now().plus(1, ChronoUnit.HOURS));
        serialNumber = BigInteger.valueOf(random.nextLong(1000000)+1);
        byte[] keyIdBytes = new KeyIdentifier(publicKey).getIdentifier();
        Extension e = new SubjectKeyIdentifierExtension(keyIdBytes);
        extensions.put(e.getId(), e);

        KeyIdentifier kid = new KeyIdentifier(caKey);
        e = new AuthorityKeyIdentifierExtension(kid, null, null);
        extensions.put(e.getId(), e);

        if (keyUsages.length != 0) {
            e = new KeyUsageExtension(keyUsage);
            extensions.put(e.getId(), e);
        }
    }



>   it also means I can't use this method to to create a certificate with a 
> longer, or shorter validity period

There are methods to set the not-before and not-after fields. Any field set in 
this static method can be changed:

`
newCertificateBuilder(...).notAfter(Date.from(Instant.now().plus(10, 
TimeUnit.YEARS)));
`

I don't like using `Date` here and would be happy to overload it to take 
`Instant` as well.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/23700#discussion_r2124330323

Reply via email to