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