001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2016, Connect2id Ltd. 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.factories; 019 020 021import java.security.Key; 022import java.security.PrivateKey; 023import java.security.interfaces.ECKey; 024import java.security.interfaces.RSAKey; 025import java.util.Collections; 026import java.util.LinkedHashSet; 027import java.util.Set; 028import javax.crypto.SecretKey; 029 030import com.nimbusds.jose.*; 031import com.nimbusds.jose.crypto.*; 032import com.nimbusds.jose.jca.JWEJCAContext; 033import com.nimbusds.jose.jwk.Curve; 034import com.nimbusds.jose.proc.JWEDecrypterFactory; 035import net.jcip.annotations.ThreadSafe; 036 037 038/** 039 * Default JSON Web Encryption (JWE) decrypter factory. 040 * 041 * <p>Supports all standard JWE algorithms implemented in the 042 * {@link com.nimbusds.jose.crypto} package. 043 * 044 * @author Vladimir Dzhuvinov 045 * @author stisve 046 * @version 2020-03-03 047 */ 048@ThreadSafe 049public class DefaultJWEDecrypterFactory implements JWEDecrypterFactory { 050 051 052 /** 053 * The supported JWE algorithms. 054 */ 055 public static final Set<JWEAlgorithm> SUPPORTED_ALGORITHMS; 056 057 058 /** 059 * The supported encryption methods. 060 */ 061 public static final Set<EncryptionMethod> SUPPORTED_ENCRYPTION_METHODS; 062 063 064 static { 065 Set<JWEAlgorithm> algs = new LinkedHashSet<>(); 066 algs.addAll(RSADecrypter.SUPPORTED_ALGORITHMS); 067 algs.addAll(ECDHDecrypter.SUPPORTED_ALGORITHMS); 068 algs.addAll(DirectDecrypter.SUPPORTED_ALGORITHMS); 069 algs.addAll(AESDecrypter.SUPPORTED_ALGORITHMS); 070 algs.addAll(PasswordBasedDecrypter.SUPPORTED_ALGORITHMS); 071 SUPPORTED_ALGORITHMS = Collections.unmodifiableSet(algs); 072 073 Set<EncryptionMethod> encs = new LinkedHashSet<>(); 074 encs.addAll(RSADecrypter.SUPPORTED_ENCRYPTION_METHODS); 075 encs.addAll(ECDHDecrypter.SUPPORTED_ENCRYPTION_METHODS); 076 encs.addAll(DirectDecrypter.SUPPORTED_ENCRYPTION_METHODS); 077 encs.addAll(AESDecrypter.SUPPORTED_ENCRYPTION_METHODS); 078 encs.addAll(PasswordBasedDecrypter.SUPPORTED_ENCRYPTION_METHODS); 079 SUPPORTED_ENCRYPTION_METHODS = Collections.unmodifiableSet(encs); 080 } 081 082 083 /** 084 * The JWE JCA context. 085 */ 086 private final JWEJCAContext jcaContext = new JWEJCAContext(); 087 088 089 @Override 090 public Set<JWEAlgorithm> supportedJWEAlgorithms() { 091 092 return SUPPORTED_ALGORITHMS; 093 } 094 095 096 @Override 097 public Set<EncryptionMethod> supportedEncryptionMethods() { 098 099 return SUPPORTED_ENCRYPTION_METHODS; 100 } 101 102 103 @Override 104 public JWEJCAContext getJCAContext() { 105 106 return jcaContext; 107 } 108 109 110 @Override 111 public JWEDecrypter createJWEDecrypter(final JWEHeader header, final Key key) 112 throws JOSEException { 113 114 final JWEDecrypter decrypter; 115 116 if (RSADecrypter.SUPPORTED_ALGORITHMS.contains(header.getAlgorithm()) && 117 RSADecrypter.SUPPORTED_ENCRYPTION_METHODS.contains(header.getEncryptionMethod())) { 118 119 if (!(key instanceof PrivateKey && key instanceof RSAKey)) { 120 throw new KeyTypeException(PrivateKey.class, RSAKey.class); 121 } 122 123 PrivateKey rsaPrivateKey = (PrivateKey)key; 124 125 decrypter = new RSADecrypter(rsaPrivateKey); 126 127 } else if (ECDHDecrypter.SUPPORTED_ALGORITHMS.contains(header.getAlgorithm()) && 128 ECDHDecrypter.SUPPORTED_ENCRYPTION_METHODS.contains(header.getEncryptionMethod())) { 129 130 if (!(key instanceof PrivateKey && key instanceof ECKey)) { 131 throw new KeyTypeException(PrivateKey.class, ECKey.class); 132 } 133 134 PrivateKey ecPrivateKey = (PrivateKey)key; 135 Curve curve = Curve.forECParameterSpec(((ECKey)key).getParams()); 136 137 decrypter = new ECDHDecrypter(ecPrivateKey, null, curve); 138 139 } else if (DirectDecrypter.SUPPORTED_ALGORITHMS.contains(header.getAlgorithm()) && 140 DirectDecrypter.SUPPORTED_ENCRYPTION_METHODS.contains(header.getEncryptionMethod())) { 141 142 if (!(key instanceof SecretKey)) { 143 throw new KeyTypeException(SecretKey.class); 144 } 145 146 SecretKey aesKey = (SecretKey)key; 147 DirectDecrypter directDecrypter = new DirectDecrypter(aesKey); 148 149 if (! directDecrypter.supportedEncryptionMethods().contains(header.getEncryptionMethod())) { 150 throw new KeyLengthException(header.getEncryptionMethod().cekBitLength(), header.getEncryptionMethod()); 151 } 152 153 decrypter = directDecrypter; 154 155 } else if (AESDecrypter.SUPPORTED_ALGORITHMS.contains(header.getAlgorithm()) && 156 AESDecrypter.SUPPORTED_ENCRYPTION_METHODS.contains(header.getEncryptionMethod())) { 157 158 if (!(key instanceof SecretKey)) { 159 throw new KeyTypeException(SecretKey.class); 160 } 161 162 SecretKey aesKey = (SecretKey)key; 163 AESDecrypter aesDecrypter = new AESDecrypter(aesKey); 164 165 if (! aesDecrypter.supportedJWEAlgorithms().contains(header.getAlgorithm())) { 166 throw new KeyLengthException(header.getAlgorithm()); 167 } 168 169 decrypter = aesDecrypter; 170 171 } else if (PasswordBasedDecrypter.SUPPORTED_ALGORITHMS.contains(header.getAlgorithm()) && 172 PasswordBasedDecrypter.SUPPORTED_ENCRYPTION_METHODS.contains(header.getEncryptionMethod())) { 173 174 if (!(key instanceof SecretKey)) { 175 throw new KeyTypeException(SecretKey.class); 176 } 177 178 byte[] password = key.getEncoded(); 179 decrypter = new PasswordBasedDecrypter(password); 180 181 } else { 182 183 throw new JOSEException("Unsupported JWE algorithm or encryption method"); 184 } 185 186 // Apply JCA context 187 decrypter.getJCAContext().setSecureRandom(jcaContext.getSecureRandom()); 188 decrypter.getJCAContext().setProvider(jcaContext.getProvider()); 189 decrypter.getJCAContext().setKeyEncryptionProvider(jcaContext.getKeyEncryptionProvider()); 190 decrypter.getJCAContext().setMACProvider(jcaContext.getMACProvider()); 191 decrypter.getJCAContext().setContentEncryptionProvider(jcaContext.getContentEncryptionProvider()); 192 193 return decrypter; 194 } 195}