001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2018, Connect2id Ltd and contributors. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.jose.jwk.gen; 019 020 021import com.google.crypto.tink.subtle.Ed25519Sign; 022import com.google.crypto.tink.subtle.X25519; 023import com.nimbusds.jose.JOSEException; 024import com.nimbusds.jose.jwk.Curve; 025import com.nimbusds.jose.jwk.OctetKeyPair; 026import com.nimbusds.jose.util.Base64URL; 027 028import java.security.GeneralSecurityException; 029import java.security.InvalidKeyException; 030import java.util.Collections; 031import java.util.LinkedHashSet; 032import java.util.Objects; 033import java.util.Set; 034 035 036/** 037 * Octet Key Pair (OKP) JSON Web Key (JWK) generator. 038 * 039 * <p>Supported curves: 040 * 041 * <ul> 042 * <li>{@link Curve#X25519 X25519} 043 * <li>{@link Curve#Ed25519 Ed25519} 044 * </ul> 045 * 046 * @author Tim McLean 047 * @version 2024-12-15 048 */ 049public class OctetKeyPairGenerator extends JWKGenerator<OctetKeyPair> { 050 051 052 /** 053 * The curve. 054 */ 055 private final Curve crv; 056 057 058 /** 059 * The supported values for the "crv" property. 060 */ 061 public static final Set<Curve> SUPPORTED_CURVES; 062 063 064 static { 065 Set<Curve> curves = new LinkedHashSet<>(); 066 curves.add(Curve.X25519); 067 curves.add(Curve.Ed25519); 068 SUPPORTED_CURVES = Collections.unmodifiableSet(curves); 069 } 070 071 072 /** 073 * Creates a new OctetKeyPair JWK generator. 074 * 075 * @param crv The curve. Must not be {@code null}. 076 */ 077 public OctetKeyPairGenerator(final Curve crv) { 078 079 if (! SUPPORTED_CURVES.contains(Objects.requireNonNull(crv))) { 080 throw new IllegalArgumentException("Curve not supported for OKP generation"); 081 } 082 this.crv = crv; 083 } 084 085 086 @Override 087 public OctetKeyPair generate() 088 throws JOSEException { 089 090 final Base64URL privateKey; 091 final Base64URL publicKey; 092 093 if (this.crv.equals(Curve.X25519)) { 094 095 final byte[] privateKeyBytes; 096 final byte[] publicKeyBytes; 097 098 try { 099 // TODO Use super.secureRandom if it is set 100 101 privateKeyBytes = X25519.generatePrivateKey(); 102 publicKeyBytes = X25519.publicFromPrivate(privateKeyBytes); 103 104 } catch (InvalidKeyException e) { 105 // internal Tink error, should not happen 106 throw new JOSEException(e.getMessage(), e); 107 } 108 109 privateKey = Base64URL.encode(privateKeyBytes); 110 publicKey = Base64URL.encode(publicKeyBytes); 111 112 } else if (this.crv.equals(Curve.Ed25519)) { 113 114 final Ed25519Sign.KeyPair tinkKeyPair; 115 116 try { 117 // TODO Use super.secureRandom if it is set 118 119 tinkKeyPair = Ed25519Sign.KeyPair.newKeyPair(); 120 121 } catch (GeneralSecurityException e) { 122 // internal Tink error, should not happen 123 throw new JOSEException(e.getMessage(), e); 124 } 125 126 privateKey = Base64URL.encode(tinkKeyPair.getPrivateKey()); 127 publicKey = Base64URL.encode(tinkKeyPair.getPublicKey()); 128 129 } else { 130 131 throw new JOSEException("Curve not supported"); 132 } 133 134 OctetKeyPair.Builder builder = new OctetKeyPair.Builder(crv, publicKey) 135 .d(privateKey) 136 .keyUse(use) 137 .keyOperations(ops) 138 .algorithm(alg) 139 .expirationTime(exp) 140 .notBeforeTime(nbf) 141 .issueTime(iat); 142 143 if (tprKid) { 144 builder.keyIDFromThumbprint(); 145 } else { 146 builder.keyID(kid); 147 } 148 149 return builder.build(); 150 } 151}