diff options
Diffstat (limited to 'bcpkix/src/main/java/org/bouncycastle/operator/jcajce')
5 files changed, 192 insertions, 3 deletions
diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaAlgorithmParametersConverter.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaAlgorithmParametersConverter.java new file mode 100644 index 0000000..d4e2162 --- /dev/null +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaAlgorithmParametersConverter.java @@ -0,0 +1,73 @@ +package org.bouncycastle.operator.jcajce; + + +import java.io.IOException; +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.MGF1ParameterSpec; + +import javax.crypto.spec.OAEPParameterSpec; +import javax.crypto.spec.PSource; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.RSAESOAEPparams; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; + +public class JcaAlgorithmParametersConverter +{ + public JcaAlgorithmParametersConverter() + { + } + + public AlgorithmIdentifier getAlgorithmIdentifier(ASN1ObjectIdentifier algId, AlgorithmParameters parameters) + throws InvalidAlgorithmParameterException + { + try + { + ASN1Encodable params = ASN1Primitive.fromByteArray(parameters.getEncoded()); + + return new AlgorithmIdentifier(algId, params); + } + catch (IOException e) + { + throw new InvalidAlgorithmParameterException("unable to encode parameters object: " + e.getMessage()); + } + } + + public AlgorithmIdentifier getAlgorithmIdentifier(ASN1ObjectIdentifier algorithm, AlgorithmParameterSpec algorithmSpec) + throws InvalidAlgorithmParameterException + { + if (algorithmSpec instanceof OAEPParameterSpec) + { + if (algorithmSpec.equals(OAEPParameterSpec.DEFAULT)) + { + return new AlgorithmIdentifier(algorithm, + new RSAESOAEPparams(RSAESOAEPparams.DEFAULT_HASH_ALGORITHM, RSAESOAEPparams.DEFAULT_MASK_GEN_FUNCTION, RSAESOAEPparams.DEFAULT_P_SOURCE_ALGORITHM)); + } + else + { + OAEPParameterSpec oaepSpec = (OAEPParameterSpec)algorithmSpec; + PSource pSource = oaepSpec.getPSource(); + + if (!oaepSpec.getMGFAlgorithm().equals(OAEPParameterSpec.DEFAULT.getMGFAlgorithm())) + { + throw new InvalidAlgorithmParameterException("only " + OAEPParameterSpec.DEFAULT.getMGFAlgorithm() + " mask generator supported."); + } + + AlgorithmIdentifier hashAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find(oaepSpec.getDigestAlgorithm()); + AlgorithmIdentifier mgf1HashAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find((((MGF1ParameterSpec)oaepSpec.getMGFParameters()).getDigestAlgorithm())); + return new AlgorithmIdentifier(algorithm, + new RSAESOAEPparams(hashAlgorithm, new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, mgf1HashAlgorithm), + new AlgorithmIdentifier(PKCSObjectIdentifiers.id_pSpecified, new DEROctetString(((PSource.PSpecified)pSource).getValue())))); + } + } + + throw new InvalidAlgorithmParameterException("unknown parameter spec passed."); + } +} diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java index 56c3771..87a6699 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JcaContentVerifierProviderBuilder.java @@ -12,6 +12,7 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; import org.bouncycastle.jcajce.DefaultJcaJceHelper; @@ -144,6 +145,12 @@ public class JcaContentVerifierProviderBuilder }; } + public ContentVerifierProvider build(SubjectPublicKeyInfo publicKey) + throws OperatorCreationException + { + return this.build(helper.convertPublicKey(publicKey)); + } + private SignatureOutputStream createSignatureStream(AlgorithmIdentifier algorithm, PublicKey publicKey) throws OperatorCreationException { diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java index 9413f96..9140ef2 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyUnwrapper.java @@ -1,5 +1,6 @@ package org.bouncycastle.operator.jcajce; +import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.Key; @@ -80,10 +81,18 @@ public class JceAsymmetricKeyUnwrapper Key sKey = null; Cipher keyCipher = helper.createAsymmetricWrapper(this.getAlgorithmIdentifier().getAlgorithm(), extraMappings); + AlgorithmParameters algParams = helper.createAlgorithmParameters(this.getAlgorithmIdentifier()); try { - keyCipher.init(Cipher.UNWRAP_MODE, privKey); + if (algParams != null) + { + keyCipher.init(Cipher.UNWRAP_MODE, privKey, algParams); + } + else + { + keyCipher.init(Cipher.UNWRAP_MODE, privKey); + } sKey = keyCipher.unwrap(encryptedKey, helper.getKeyAlgorithmName(encryptedKeyAlgorithm.getAlgorithm()), Cipher.SECRET_KEY); } catch (GeneralSecurityException e) diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyWrapper.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyWrapper.java index 4a2ffae..d19dbcf 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyWrapper.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/JceAsymmetricKeyWrapper.java @@ -1,6 +1,8 @@ package org.bouncycastle.operator.jcajce; +import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; import java.security.Provider; import java.security.ProviderException; import java.security.PublicKey; @@ -12,6 +14,7 @@ import java.util.Map; import javax.crypto.Cipher; import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.jcajce.DefaultJcaJceHelper; import org.bouncycastle.jcajce.NamedJcaJceHelper; @@ -40,6 +43,19 @@ public class JceAsymmetricKeyWrapper this(certificate.getPublicKey()); } + /** + * Create a wrapper, overriding the algorithm type that is stored in the public key. + * + * @param algorithmIdentifier identifier for encryption algorithm to be used. + * @param publicKey the public key to be used. + */ + public JceAsymmetricKeyWrapper(AlgorithmIdentifier algorithmIdentifier, PublicKey publicKey) + { + super(algorithmIdentifier); + + this.publicKey = publicKey; + } + public JceAsymmetricKeyWrapper setProvider(Provider provider) { this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider)); @@ -86,13 +102,25 @@ public class JceAsymmetricKeyWrapper throws OperatorException { Cipher keyEncryptionCipher = helper.createAsymmetricWrapper(getAlgorithmIdentifier().getAlgorithm(), extraMappings); + AlgorithmParameters algParams = helper.createAlgorithmParameters(this.getAlgorithmIdentifier()); + byte[] encryptedKeyBytes = null; try { - keyEncryptionCipher.init(Cipher.WRAP_MODE, publicKey, random); + if (algParams != null) + { + keyEncryptionCipher.init(Cipher.WRAP_MODE, publicKey, algParams, random); + } + else + { + keyEncryptionCipher.init(Cipher.WRAP_MODE, publicKey, random); + } encryptedKeyBytes = keyEncryptionCipher.wrap(OperatorUtils.getJceKey(encryptionKey)); } + catch (InvalidKeyException e) + { + } catch (GeneralSecurityException e) { } @@ -114,6 +142,10 @@ public class JceAsymmetricKeyWrapper keyEncryptionCipher.init(Cipher.ENCRYPT_MODE, publicKey, random); encryptedKeyBytes = keyEncryptionCipher.doFinal(OperatorUtils.getJceKey(encryptionKey).getEncoded()); } + catch (InvalidKeyException e) + { + throw new OperatorException("unable to encrypt contents key", e); + } catch (GeneralSecurityException e) { throw new OperatorException("unable to encrypt contents key", e); diff --git a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java index bdffa53..2e0bcc1 100644 --- a/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java +++ b/bcpkix/src/main/java/org/bouncycastle/operator/jcajce/OperatorHelper.java @@ -4,14 +4,18 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; +import java.security.KeyFactory; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.security.PublicKey; import java.security.Signature; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; import java.security.spec.PSSParameterSpec; +import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; @@ -29,9 +33,11 @@ import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.pkcs.RSASSAPSSparams; import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.jcajce.JcaJceHelper; +import org.bouncycastle.jcajce.JcaJceUtils; import org.bouncycastle.operator.OperatorCreationException; class OperatorHelper @@ -181,6 +187,41 @@ class OperatorHelper } } + AlgorithmParameters createAlgorithmParameters(AlgorithmIdentifier cipherAlgId) + throws OperatorCreationException + { + AlgorithmParameters parameters; + + if (cipherAlgId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)) + { + return null; + } + + try + { + parameters = helper.createAlgorithmParameters(cipherAlgId.getAlgorithm().getId()); + } + catch (NoSuchAlgorithmException e) + { + return null; // There's a good chance there aren't any! + } + catch (NoSuchProviderException e) + { + throw new OperatorCreationException("cannot create algorithm parameters: " + e.getMessage(), e); + } + + try + { + parameters.init(cipherAlgId.getParameters().toASN1Primitive().getEncoded()); + } + catch (IOException e) + { + throw new OperatorCreationException("cannot initialise algorithm parameters: " + e.getMessage(), e); + } + + return parameters; + } + MessageDigest createDigest(AlgorithmIdentifier digAlgId) throws GeneralSecurityException { @@ -258,7 +299,7 @@ class OperatorHelper { AlgorithmParameters params = helper.createAlgorithmParameters(algName); - params.init(algorithm.getParameters().toASN1Primitive().getEncoded(), "ASN.1"); + JcaJceUtils.loadParameters(params, algorithm.getParameters()); PSSParameterSpec spec = (PSSParameterSpec)params.getParameterSpec(PSSParameterSpec.class); sig.setParameter(spec); @@ -367,6 +408,33 @@ class OperatorHelper } } + public PublicKey convertPublicKey(SubjectPublicKeyInfo publicKeyInfo) + throws OperatorCreationException + { + try + { + KeyFactory keyFact = helper.createKeyFactory(publicKeyInfo.getAlgorithm().getAlgorithm().getId()); + + return keyFact.generatePublic(new X509EncodedKeySpec(publicKeyInfo.getEncoded())); + } + catch (IOException e) + { + throw new OperatorCreationException("cannot get encoded form of key: " + e.getMessage(), e); + } + catch (NoSuchAlgorithmException e) + { + throw new OperatorCreationException("cannot create key factory: " + e.getMessage(), e); + } + catch (NoSuchProviderException e) + { + throw new OperatorCreationException("cannot find factory provider: " + e.getMessage(), e); + } + catch (InvalidKeySpecException e) + { + throw new OperatorCreationException("cannot create key factory: " + e.getMessage(), e); + } + } + // TODO: put somewhere public so cause easily accessed private static class OpCertificateException extends CertificateException |