| package org.bouncycastle.jce.provider; |
| |
| import java.lang.reflect.Constructor; |
| import java.security.InvalidKeyException; |
| import java.security.spec.InvalidKeySpecException; |
| import java.security.spec.KeySpec; |
| |
| import javax.crypto.SecretKey; |
| import javax.crypto.SecretKeyFactorySpi; |
| import javax.crypto.spec.DESKeySpec; |
| import javax.crypto.spec.PBEKeySpec; |
| import javax.crypto.spec.SecretKeySpec; |
| |
| import org.bouncycastle.asn1.DERObjectIdentifier; |
| import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; |
| import org.bouncycastle.crypto.CipherParameters; |
| import org.bouncycastle.crypto.params.DESParameters; |
| import org.bouncycastle.crypto.params.KeyParameter; |
| import org.bouncycastle.crypto.params.ParametersWithIV; |
| import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey; |
| import org.bouncycastle.jcajce.provider.symmetric.util.PBE; |
| |
| public class JCESecretKeyFactory |
| extends SecretKeyFactorySpi |
| implements PBE |
| { |
| protected String algName; |
| protected DERObjectIdentifier algOid; |
| |
| protected JCESecretKeyFactory( |
| String algName, |
| DERObjectIdentifier algOid) |
| { |
| this.algName = algName; |
| this.algOid = algOid; |
| } |
| |
| protected SecretKey engineGenerateSecret( |
| KeySpec keySpec) |
| throws InvalidKeySpecException |
| { |
| if (keySpec instanceof SecretKeySpec) |
| { |
| return (SecretKey)keySpec; |
| } |
| |
| throw new InvalidKeySpecException("Invalid KeySpec"); |
| } |
| |
| protected KeySpec engineGetKeySpec( |
| SecretKey key, |
| Class keySpec) |
| throws InvalidKeySpecException |
| { |
| if (keySpec == null) |
| { |
| throw new InvalidKeySpecException("keySpec parameter is null"); |
| } |
| if (key == null) |
| { |
| throw new InvalidKeySpecException("key parameter is null"); |
| } |
| |
| if (SecretKeySpec.class.isAssignableFrom(keySpec)) |
| { |
| return new SecretKeySpec(key.getEncoded(), algName); |
| } |
| |
| try |
| { |
| Class[] parameters = { byte[].class }; |
| |
| Constructor c = keySpec.getConstructor(parameters); |
| Object[] p = new Object[1]; |
| |
| p[0] = key.getEncoded(); |
| |
| return (KeySpec)c.newInstance(p); |
| } |
| catch (Exception e) |
| { |
| throw new InvalidKeySpecException(e.toString()); |
| } |
| } |
| |
| protected SecretKey engineTranslateKey( |
| SecretKey key) |
| throws InvalidKeyException |
| { |
| if (key == null) |
| { |
| throw new InvalidKeyException("key parameter is null"); |
| } |
| |
| if (!key.getAlgorithm().equalsIgnoreCase(algName)) |
| { |
| throw new InvalidKeyException("Key not of type " + algName + "."); |
| } |
| |
| return new SecretKeySpec(key.getEncoded(), algName); |
| } |
| |
| /* |
| * classes that inherit from us |
| */ |
| |
| static public class PBEKeyFactory |
| extends JCESecretKeyFactory |
| { |
| private boolean forCipher; |
| private int scheme; |
| private int digest; |
| private int keySize; |
| private int ivSize; |
| |
| public PBEKeyFactory( |
| String algorithm, |
| DERObjectIdentifier oid, |
| boolean forCipher, |
| int scheme, |
| int digest, |
| int keySize, |
| int ivSize) |
| { |
| super(algorithm, oid); |
| |
| this.forCipher = forCipher; |
| this.scheme = scheme; |
| this.digest = digest; |
| this.keySize = keySize; |
| this.ivSize = ivSize; |
| } |
| |
| protected SecretKey engineGenerateSecret( |
| KeySpec keySpec) |
| throws InvalidKeySpecException |
| { |
| if (keySpec instanceof PBEKeySpec) |
| { |
| PBEKeySpec pbeSpec = (PBEKeySpec)keySpec; |
| CipherParameters param; |
| |
| if (pbeSpec.getSalt() == null) |
| { |
| return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, null); |
| } |
| |
| if (forCipher) |
| { |
| param = Util.makePBEParameters(pbeSpec, scheme, digest, keySize, ivSize); |
| } |
| else |
| { |
| param = Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize); |
| } |
| |
| return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param); |
| } |
| |
| throw new InvalidKeySpecException("Invalid KeySpec"); |
| } |
| } |
| |
| static public class DESPBEKeyFactory |
| extends JCESecretKeyFactory |
| { |
| private boolean forCipher; |
| private int scheme; |
| private int digest; |
| private int keySize; |
| private int ivSize; |
| |
| public DESPBEKeyFactory( |
| String algorithm, |
| DERObjectIdentifier oid, |
| boolean forCipher, |
| int scheme, |
| int digest, |
| int keySize, |
| int ivSize) |
| { |
| super(algorithm, oid); |
| |
| this.forCipher = forCipher; |
| this.scheme = scheme; |
| this.digest = digest; |
| this.keySize = keySize; |
| this.ivSize = ivSize; |
| } |
| |
| protected SecretKey engineGenerateSecret( |
| KeySpec keySpec) |
| throws InvalidKeySpecException |
| { |
| if (keySpec instanceof PBEKeySpec) |
| { |
| PBEKeySpec pbeSpec = (PBEKeySpec)keySpec; |
| CipherParameters param; |
| |
| if (pbeSpec.getSalt() == null) |
| { |
| return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, null); |
| } |
| |
| if (forCipher) |
| { |
| param = Util.makePBEParameters(pbeSpec, scheme, digest, keySize, ivSize); |
| } |
| else |
| { |
| param = Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize); |
| } |
| |
| KeyParameter kParam; |
| if (param instanceof ParametersWithIV) |
| { |
| kParam = (KeyParameter)((ParametersWithIV)param).getParameters(); |
| } |
| else |
| { |
| kParam = (KeyParameter)param; |
| } |
| |
| DESParameters.setOddParity(kParam.getKey()); |
| |
| return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param); |
| } |
| |
| throw new InvalidKeySpecException("Invalid KeySpec"); |
| } |
| } |
| |
| static public class DES |
| extends JCESecretKeyFactory |
| { |
| public DES() |
| { |
| super("DES", null); |
| } |
| |
| protected SecretKey engineGenerateSecret( |
| KeySpec keySpec) |
| throws InvalidKeySpecException |
| { |
| if (keySpec instanceof DESKeySpec) |
| { |
| DESKeySpec desKeySpec = (DESKeySpec)keySpec; |
| return new SecretKeySpec(desKeySpec.getKey(), "DES"); |
| } |
| |
| return super.engineGenerateSecret(keySpec); |
| } |
| } |
| |
| // BEGIN android-removed |
| // /** |
| // * PBEWithMD2AndDES |
| // */ |
| // static public class PBEWithMD2AndDES |
| // extends DESPBEKeyFactory |
| // { |
| // public PBEWithMD2AndDES() |
| // { |
| // super("PBEwithMD2andDES", PKCSObjectIdentifiers.pbeWithMD2AndDES_CBC, true, PKCS5S1, MD2, 64, 64); |
| // } |
| // } |
| // |
| // /** |
| // * PBEWithMD2AndRC2 |
| // */ |
| // static public class PBEWithMD2AndRC2 |
| // extends PBEKeyFactory |
| // { |
| // public PBEWithMD2AndRC2() |
| // { |
| // super("PBEwithMD2andRC2", PKCSObjectIdentifiers.pbeWithMD2AndRC2_CBC, true, PKCS5S1, MD2, 64, 64); |
| // } |
| // } |
| // END android-removed |
| |
| /** |
| * PBEWithMD5AndDES |
| */ |
| static public class PBEWithMD5AndDES |
| extends DESPBEKeyFactory |
| { |
| public PBEWithMD5AndDES() |
| { |
| super("PBEwithMD5andDES", PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC, true, PKCS5S1, MD5, 64, 64); |
| } |
| } |
| |
| /** |
| * PBEWithMD5AndRC2 |
| */ |
| static public class PBEWithMD5AndRC2 |
| extends PBEKeyFactory |
| { |
| public PBEWithMD5AndRC2() |
| { |
| super("PBEwithMD5andRC2", PKCSObjectIdentifiers.pbeWithMD5AndRC2_CBC, true, PKCS5S1, MD5, 64, 64); |
| } |
| } |
| |
| /** |
| * PBEWithSHA1AndDES |
| */ |
| static public class PBEWithSHA1AndDES |
| extends DESPBEKeyFactory |
| { |
| public PBEWithSHA1AndDES() |
| { |
| super("PBEwithSHA1andDES", PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC, true, PKCS5S1, SHA1, 64, 64); |
| } |
| } |
| |
| /** |
| * PBEWithSHA1AndRC2 |
| */ |
| static public class PBEWithSHA1AndRC2 |
| extends PBEKeyFactory |
| { |
| public PBEWithSHA1AndRC2() |
| { |
| super("PBEwithSHA1andRC2", PKCSObjectIdentifiers.pbeWithSHA1AndRC2_CBC, true, PKCS5S1, SHA1, 64, 64); |
| } |
| } |
| |
| /** |
| * PBEWithSHAAnd3-KeyTripleDES-CBC |
| */ |
| static public class PBEWithSHAAndDES3Key |
| extends DESPBEKeyFactory |
| { |
| public PBEWithSHAAndDES3Key() |
| { |
| super("PBEwithSHAandDES3Key-CBC", PKCSObjectIdentifiers.pbeWithSHAAnd3_KeyTripleDES_CBC, true, PKCS12, SHA1, 192, 64); |
| } |
| } |
| |
| /** |
| * PBEWithSHAAnd2-KeyTripleDES-CBC |
| */ |
| static public class PBEWithSHAAndDES2Key |
| extends DESPBEKeyFactory |
| { |
| public PBEWithSHAAndDES2Key() |
| { |
| super("PBEwithSHAandDES2Key-CBC", PKCSObjectIdentifiers.pbeWithSHAAnd2_KeyTripleDES_CBC, true, PKCS12, SHA1, 128, 64); |
| } |
| } |
| |
| /** |
| * PBEWithSHAAnd128BitRC2-CBC |
| */ |
| static public class PBEWithSHAAnd128BitRC2 |
| extends PBEKeyFactory |
| { |
| public PBEWithSHAAnd128BitRC2() |
| { |
| super("PBEwithSHAand128BitRC2-CBC", PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC2_CBC, true, PKCS12, SHA1, 128, 64); |
| } |
| } |
| |
| /** |
| * PBEWithSHAAnd40BitRC2-CBC |
| */ |
| static public class PBEWithSHAAnd40BitRC2 |
| extends PBEKeyFactory |
| { |
| public PBEWithSHAAnd40BitRC2() |
| { |
| super("PBEwithSHAand40BitRC2-CBC", PKCSObjectIdentifiers.pbeWithSHAAnd40BitRC2_CBC, true, PKCS12, SHA1, 40, 64); |
| } |
| } |
| |
| /** |
| * PBEWithSHAAndTwofish-CBC |
| */ |
| static public class PBEWithSHAAndTwofish |
| extends PBEKeyFactory |
| { |
| public PBEWithSHAAndTwofish() |
| { |
| super("PBEwithSHAandTwofish-CBC", null, true, PKCS12, SHA1, 256, 128); |
| } |
| } |
| |
| /** |
| * PBEWithSHAAnd128BitRC4 |
| */ |
| static public class PBEWithSHAAnd128BitRC4 |
| extends PBEKeyFactory |
| { |
| public PBEWithSHAAnd128BitRC4() |
| { |
| super("PBEWithSHAAnd128BitRC4", PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC4, true, PKCS12, SHA1, 128, 0); |
| } |
| } |
| |
| /** |
| * PBEWithSHAAnd40BitRC4 |
| */ |
| static public class PBEWithSHAAnd40BitRC4 |
| extends PBEKeyFactory |
| { |
| public PBEWithSHAAnd40BitRC4() |
| { |
| super("PBEWithSHAAnd128BitRC4", PKCSObjectIdentifiers.pbeWithSHAAnd128BitRC4, true, PKCS12, SHA1, 40, 0); |
| } |
| } |
| |
| // BEGIN android-removed |
| // /** |
| // * PBEWithHmacRIPEMD160 |
| // */ |
| // public static class PBEWithRIPEMD160 |
| // extends PBEKeyFactory |
| // { |
| // public PBEWithRIPEMD160() |
| // { |
| // super("PBEwithHmacRIPEMD160", null, false, PKCS12, RIPEMD160, 160, 0); |
| // } |
| // } |
| // END android-removed |
| |
| /** |
| * PBEWithHmacSHA |
| */ |
| public static class PBEWithSHA |
| extends PBEKeyFactory |
| { |
| public PBEWithSHA() |
| { |
| super("PBEwithHmacSHA", null, false, PKCS12, SHA1, 160, 0); |
| } |
| } |
| |
| // BEGIN android-removed |
| // /** |
| // * PBEWithHmacTiger |
| // */ |
| // public static class PBEWithTiger |
| // extends PBEKeyFactory |
| // { |
| // public PBEWithTiger() |
| // { |
| // super("PBEwithHmacTiger", null, false, PKCS12, TIGER, 192, 0); |
| // } |
| // } |
| // END android-removed |
| |
| /** |
| * PBEWithSHA1And128BitAES-BC |
| */ |
| static public class PBEWithSHAAnd128BitAESBC |
| extends PBEKeyFactory |
| { |
| public PBEWithSHAAnd128BitAESBC() |
| { |
| super("PBEWithSHA1And128BitAES-CBC-BC", null, true, PKCS12, SHA1, 128, 128); |
| } |
| } |
| |
| /** |
| * PBEWithSHA1And192BitAES-BC |
| */ |
| static public class PBEWithSHAAnd192BitAESBC |
| extends PBEKeyFactory |
| { |
| public PBEWithSHAAnd192BitAESBC() |
| { |
| super("PBEWithSHA1And192BitAES-CBC-BC", null, true, PKCS12, SHA1, 192, 128); |
| } |
| } |
| |
| /** |
| * PBEWithSHA1And256BitAES-BC |
| */ |
| static public class PBEWithSHAAnd256BitAESBC |
| extends PBEKeyFactory |
| { |
| public PBEWithSHAAnd256BitAESBC() |
| { |
| super("PBEWithSHA1And256BitAES-CBC-BC", null, true, PKCS12, SHA1, 256, 128); |
| } |
| } |
| |
| /** |
| * PBEWithSHA256And128BitAES-BC |
| */ |
| static public class PBEWithSHA256And128BitAESBC |
| extends PBEKeyFactory |
| { |
| public PBEWithSHA256And128BitAESBC() |
| { |
| super("PBEWithSHA256And128BitAES-CBC-BC", null, true, PKCS12, SHA256, 128, 128); |
| } |
| } |
| |
| /** |
| * PBEWithSHA256And192BitAES-BC |
| */ |
| static public class PBEWithSHA256And192BitAESBC |
| extends PBEKeyFactory |
| { |
| public PBEWithSHA256And192BitAESBC() |
| { |
| super("PBEWithSHA256And192BitAES-CBC-BC", null, true, PKCS12, SHA256, 192, 128); |
| } |
| } |
| |
| /** |
| * PBEWithSHA256And256BitAES-BC |
| */ |
| static public class PBEWithSHA256And256BitAESBC |
| extends PBEKeyFactory |
| { |
| public PBEWithSHA256And256BitAESBC() |
| { |
| super("PBEWithSHA256And256BitAES-CBC-BC", null, true, PKCS12, SHA256, 256, 128); |
| } |
| } |
| |
| /** |
| * PBEWithMD5And128BitAES-OpenSSL |
| */ |
| static public class PBEWithMD5And128BitAESCBCOpenSSL |
| extends PBEKeyFactory |
| { |
| public PBEWithMD5And128BitAESCBCOpenSSL() |
| { |
| super("PBEWithMD5And128BitAES-CBC-OpenSSL", null, true, OPENSSL, MD5, 128, 128); |
| } |
| } |
| |
| /** |
| * PBEWithMD5And192BitAES-OpenSSL |
| */ |
| static public class PBEWithMD5And192BitAESCBCOpenSSL |
| extends PBEKeyFactory |
| { |
| public PBEWithMD5And192BitAESCBCOpenSSL() |
| { |
| super("PBEWithMD5And192BitAES-CBC-OpenSSL", null, true, OPENSSL, MD5, 192, 128); |
| } |
| } |
| |
| /** |
| * PBEWithMD5And256BitAES-OpenSSL |
| */ |
| static public class PBEWithMD5And256BitAESCBCOpenSSL |
| extends PBEKeyFactory |
| { |
| public PBEWithMD5And256BitAESCBCOpenSSL() |
| { |
| super("PBEWithMD5And256BitAES-CBC-OpenSSL", null, true, OPENSSL, MD5, 256, 128); |
| } |
| } |
| // BEGIN android-added |
| static public class PBKDF2WithHmacSHA1 |
| extends JCESecretKeyFactory |
| { |
| public PBKDF2WithHmacSHA1() |
| { |
| super("PBKDF2WithHmacSHA1", PKCSObjectIdentifiers.id_PBKDF2); |
| } |
| |
| protected SecretKey engineGenerateSecret( |
| KeySpec keySpec) |
| throws InvalidKeySpecException |
| { |
| if (keySpec instanceof PBEKeySpec) |
| { |
| PBEKeySpec pbeSpec = (PBEKeySpec)keySpec; |
| |
| if (pbeSpec.getSalt() == null) |
| { |
| throw new InvalidKeySpecException("missing required salt"); |
| } |
| |
| if (pbeSpec.getIterationCount() <= 0) |
| { |
| throw new InvalidKeySpecException("positive iteration count required: " |
| + pbeSpec.getIterationCount()); |
| } |
| |
| if (pbeSpec.getKeyLength() <= 0) |
| { |
| throw new InvalidKeySpecException("positive key length required: " |
| + pbeSpec.getKeyLength()); |
| } |
| |
| if (pbeSpec.getPassword().length == 0) |
| { |
| throw new IllegalArgumentException("password empty"); |
| } |
| |
| int scheme = PKCS5S2; |
| int digest = SHA1; |
| int keySize = pbeSpec.getKeyLength(); |
| int ivSize = -1; |
| CipherParameters param = Util.makePBEMacParameters(pbeSpec, scheme, digest, keySize); |
| |
| return new BCPBEKey(this.algName, this.algOid, scheme, digest, keySize, ivSize, pbeSpec, param); |
| } |
| |
| throw new InvalidKeySpecException("Invalid KeySpec"); |
| } |
| } |
| // END android-added |
| } |