001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2021, 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.crypto; 019 020 021import com.nimbusds.jose.*; 022import com.nimbusds.jose.crypto.impl.AAD; 023import com.nimbusds.jose.crypto.impl.ECDH1PU; 024import com.nimbusds.jose.crypto.impl.ECDH1PUCryptoProvider; 025import com.nimbusds.jose.jwk.Curve; 026import com.nimbusds.jose.jwk.OctetKeyPair; 027import com.nimbusds.jose.jwk.gen.OctetKeyPairGenerator; 028import net.jcip.annotations.ThreadSafe; 029 030import javax.crypto.SecretKey; 031import java.util.Arrays; 032import java.util.Collections; 033import java.util.Set; 034 035 036/** 037 * Elliptic Curve Diffie-Hellman encrypter of 038 * {@link com.nimbusds.jose.JWEObject JWE objects} for curves using an OKP JWK. 039 * Expects a public {@link OctetKeyPair} key with {@code "crv"} X25519. 040 * 041 * <p>See <a href="https://tools.ietf.org/html/rfc8037">RFC 8037</a> 042 * for more information. 043 * 044 * <p>See also {@link ECDH1PUEncrypter} for ECDH on other curves. 045 * 046 * <p>Public Key Authenticated Encryption for JOSE 047 * <a href="https://datatracker.ietf.org/doc/html/draft-madden-jose-ecdh-1pu-04">ECDH-1PU</a> 048 * for more information. 049 * 050 * <p>This class is thread-safe. 051 * 052 * <p>Supports the following key management algorithms: 053 * 054 * <ul> 055 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU} 056 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A128KW} 057 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A192KW} 058 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A256KW} 059 * </ul> 060 * 061 * <p>Supports the following elliptic curves: 062 * 063 * <ul> 064 * <li>{@link Curve#X25519} 065 * </ul> 066 * 067 * <p>Supports the following content encryption algorithms for Direct key 068 * agreement mode: 069 * 070 * <ul> 071 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256} 072 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384} 073 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512} 074 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128GCM} 075 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192GCM} 076 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256GCM} 077 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED} 078 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED} 079 * <li>{@link com.nimbusds.jose.EncryptionMethod#XC20P} 080 * </ul> 081 * 082 * <p>Supports the following content encryption algorithms for Key wrapping 083 * mode: 084 * 085 * <ul> 086 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256} 087 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384} 088 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512} 089 * </ul> 090 * 091 * @author Alexander Martynov 092 * @author Egor Puzanov 093 * @version 2023-05-17 094 */ 095@ThreadSafe 096public class ECDH1PUX25519Encrypter extends ECDH1PUCryptoProvider implements JWEEncrypter { 097 098 099 /** 100 * The public key. 101 */ 102 private final OctetKeyPair publicKey; 103 104 /** 105 * The private key. 106 */ 107 private final OctetKeyPair privateKey; 108 109 /** 110 * Creates a new Curve25519 Elliptic Curve Diffie-Hellman encrypter. 111 * 112 * @param privateKey The private key. Must not be {@code null}. 113 * @param publicKey The public key. Must not be {@code null}. 114 * 115 * @throws JOSEException If the key subtype is not supported. 116 */ 117 public ECDH1PUX25519Encrypter(final OctetKeyPair privateKey, final OctetKeyPair publicKey) 118 throws JOSEException { 119 120 this(privateKey, publicKey, null); 121 } 122 123 /** 124 * Creates a new Curve25519 Elliptic Curve Diffie-Hellman encrypter. 125 * 126 * @param privateKey The private key. Must not be {@code null}. 127 * @param publicKey The public key. Must not be {@code null}. 128 * @param contentEncryptionKey The content encryption key (CEK) to use. 129 * If specified its algorithm must be "AES" 130 * and its length must match the expected 131 * for the JWE encryption method ("enc"). 132 * If {@code null} a CEK will be generated 133 * for each JWE. 134 * 135 * @throws JOSEException If the key subtype is not supported. 136 */ 137 public ECDH1PUX25519Encrypter(final OctetKeyPair privateKey, 138 final OctetKeyPair publicKey, 139 final SecretKey contentEncryptionKey 140 ) 141 throws JOSEException { 142 143 super(publicKey.getCurve(), contentEncryptionKey); 144 145 this.publicKey = publicKey; 146 this.privateKey = privateKey; 147 } 148 149 @Override 150 public Set<Curve> supportedEllipticCurves() { 151 152 return Collections.singleton(Curve.X25519); 153 } 154 155 156 /** 157 * Returns the public key. 158 * 159 * @return The public key. 160 */ 161 public OctetKeyPair getPublicKey() { 162 163 return publicKey; 164 } 165 166 /** 167 * Returns the private key. 168 * 169 * @return The private key. 170 */ 171 public OctetKeyPair getPrivateKey() { 172 173 return privateKey; 174 } 175 176 177 /** 178 * Encrypts the specified clear text of a {@link JWEObject JWE object}. 179 * 180 * @param header The JSON Web Encryption (JWE) header. Must specify 181 * a supported JWE algorithm and method. Must not be 182 * {@code null}. 183 * @param clearText The clear text to encrypt. Must not be {@code null}. 184 * 185 * @return The resulting JWE crypto parts. 186 * 187 * @throws JOSEException If the JWE algorithm or method is not 188 * supported or if encryption failed for some 189 * other internal reason. 190 */ 191 @Deprecated 192 public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText) 193 throws JOSEException { 194 195 return encrypt(header, clearText, AAD.compute(header)); 196 } 197 198 199 @Override 200 public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText, final byte[] aad) 201 throws JOSEException { 202 203 final OctetKeyPair ephemeralPrivateKey = new OctetKeyPairGenerator(getCurve()).generate(); 204 final OctetKeyPair ephemeralPublicKey = ephemeralPrivateKey.toPublicJWK(); 205 206 // Add the ephemeral public EC key to the header 207 JWEHeader updatedHeader = new JWEHeader.Builder(header). 208 ephemeralPublicKey(ephemeralPublicKey). 209 build(); 210 211 SecretKey Z = ECDH1PU.deriveSenderZ( 212 privateKey, 213 publicKey, 214 ephemeralPrivateKey 215 ); 216 217 // for JWEObject we need update the AAD as well 218 final byte[] updatedAAD = Arrays.equals(AAD.compute(header), aad) ? AAD.compute(updatedHeader) : aad; 219 220 return encryptWithZ(updatedHeader, Z, clearText, updatedAAD); 221 } 222}