1import com.nimbusds.jose.JOSEObjectType;
2import com.nimbusds.jose.JWSAlgorithm;
3import com.nimbusds.jose.JWSHeader;
4import com.nimbusds.jose.crypto.ECDSASigner;
5import com.nimbusds.jwt.JWTClaimsSet;
6import com.nimbusds.jwt.SignedJWT;
7import java.nio.file.Files;
8import java.nio.file.Path;
9import java.security.KeyFactory;
10import java.security.interfaces.ECPrivateKey;
11import java.security.spec.PKCS8EncodedKeySpec;
12import java.time.Instant;
13import java.time.temporal.ChronoUnit;
14import java.util.Base64;
15import java.util.Date;
16
17public class SignJwt {
18 public static void main(String[] args) throws Exception {
19 String pem = Files.readString(Path.of("key.pem"));
20 byte[] pkcs8 = Base64.getMimeDecoder().decode(pem.replaceAll("-----[^-]+-----", ""));
21 ECPrivateKey privateKey = (ECPrivateKey) KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(pkcs8));
22
23 Instant now = Instant.now().truncatedTo(ChronoUnit.SECONDS);
24 JWTClaimsSet claims = new JWTClaimsSet.Builder()
25 .issuer("https://issuer.example.com")
26 .subject("user-42")
27 .audience("api://orders")
28 .issueTime(Date.from(now))
29 .expirationTime(Date.from(now.plusSeconds(15 * 60)))
30 .build();
31 JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.ES256)
32 .type(JOSEObjectType.JWT)
33 .keyID("2026-10")
34 .build();
35
36 SignedJWT jwt = new SignedJWT(header, claims);
37 jwt.sign(new ECDSASigner(privateKey)); // produces the 64-byte JWS form, not the JCA's DER
38 System.out.println(jwt.serialize());
39 }
40}
41