diff options
Diffstat (limited to 'pkix/src/main/java/org/spongycastle/operator/bc')
22 files changed, 1036 insertions, 0 deletions
diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/AESUtil.java b/pkix/src/main/java/org/spongycastle/operator/bc/AESUtil.java new file mode 100644 index 00000000..7abd31be --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/AESUtil.java @@ -0,0 +1,34 @@ +package org.spongycastle.operator.bc; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.nist.NISTObjectIdentifiers; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.params.KeyParameter; + +class AESUtil +{ + static AlgorithmIdentifier determineKeyEncAlg(KeyParameter key) + { + int length = key.getKey().length * 8; + ASN1ObjectIdentifier wrapOid; + + if (length == 128) + { + wrapOid = NISTObjectIdentifiers.id_aes128_wrap; + } + else if (length == 192) + { + wrapOid = NISTObjectIdentifiers.id_aes192_wrap; + } + else if (length == 256) + { + wrapOid = NISTObjectIdentifiers.id_aes256_wrap; + } + else + { + throw new IllegalArgumentException("illegal keysize in AES"); + } + + return new AlgorithmIdentifier(wrapOid); // parameters absent + } +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcAESSymmetricKeyUnwrapper.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcAESSymmetricKeyUnwrapper.java new file mode 100644 index 00000000..f9b8c09b --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcAESSymmetricKeyUnwrapper.java @@ -0,0 +1,13 @@ +package org.spongycastle.operator.bc; + +import org.spongycastle.crypto.engines.AESWrapEngine; +import org.spongycastle.crypto.params.KeyParameter; + +public class BcAESSymmetricKeyUnwrapper + extends BcSymmetricKeyUnwrapper +{ + public BcAESSymmetricKeyUnwrapper(KeyParameter wrappingKey) + { + super(AESUtil.determineKeyEncAlg(wrappingKey), new AESWrapEngine(), wrappingKey); + } +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcAESSymmetricKeyWrapper.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcAESSymmetricKeyWrapper.java new file mode 100644 index 00000000..62dc062f --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcAESSymmetricKeyWrapper.java @@ -0,0 +1,13 @@ +package org.spongycastle.operator.bc; + +import org.spongycastle.crypto.engines.AESWrapEngine; +import org.spongycastle.crypto.params.KeyParameter; + +public class BcAESSymmetricKeyWrapper + extends BcSymmetricKeyWrapper +{ + public BcAESSymmetricKeyWrapper(KeyParameter wrappingKey) + { + super(AESUtil.determineKeyEncAlg(wrappingKey), new AESWrapEngine(), wrappingKey); + } +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcAsymmetricKeyUnwrapper.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcAsymmetricKeyUnwrapper.java new file mode 100644 index 00000000..8fed9deb --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcAsymmetricKeyUnwrapper.java @@ -0,0 +1,51 @@ +package org.spongycastle.operator.bc; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.AsymmetricBlockCipher; +import org.spongycastle.crypto.InvalidCipherTextException; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.operator.AsymmetricKeyUnwrapper; +import org.spongycastle.operator.GenericKey; +import org.spongycastle.operator.OperatorException; + +public abstract class BcAsymmetricKeyUnwrapper + extends AsymmetricKeyUnwrapper +{ + private AsymmetricKeyParameter privateKey; + + public BcAsymmetricKeyUnwrapper(AlgorithmIdentifier encAlgId, AsymmetricKeyParameter privateKey) + { + super(encAlgId); + + this.privateKey = privateKey; + } + + public GenericKey generateUnwrappedKey(AlgorithmIdentifier encryptedKeyAlgorithm, byte[] encryptedKey) + throws OperatorException + { + AsymmetricBlockCipher keyCipher = createAsymmetricUnwrapper(this.getAlgorithmIdentifier().getAlgorithm()); + + keyCipher.init(false, privateKey); + try + { + byte[] key = keyCipher.processBlock(encryptedKey, 0, encryptedKey.length); + + if (encryptedKeyAlgorithm.getAlgorithm().equals(PKCSObjectIdentifiers.des_EDE3_CBC)) + { + return new GenericKey(encryptedKeyAlgorithm, key); + } + else + { + return new GenericKey(encryptedKeyAlgorithm, key); + } + } + catch (InvalidCipherTextException e) + { + throw new OperatorException("unable to recover secret key: " + e.getMessage(), e); + } + } + + protected abstract AsymmetricBlockCipher createAsymmetricUnwrapper(ASN1ObjectIdentifier algorithm); +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcAsymmetricKeyWrapper.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcAsymmetricKeyWrapper.java new file mode 100644 index 00000000..8b5bb3e8 --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcAsymmetricKeyWrapper.java @@ -0,0 +1,60 @@ +package org.spongycastle.operator.bc; + +import java.security.SecureRandom; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.AsymmetricBlockCipher; +import org.spongycastle.crypto.CipherParameters; +import org.spongycastle.crypto.InvalidCipherTextException; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.params.ParametersWithRandom; +import org.spongycastle.operator.AsymmetricKeyWrapper; +import org.spongycastle.operator.GenericKey; +import org.spongycastle.operator.OperatorException; + +public abstract class BcAsymmetricKeyWrapper + extends AsymmetricKeyWrapper +{ + private AsymmetricKeyParameter publicKey; + private SecureRandom random; + + public BcAsymmetricKeyWrapper(AlgorithmIdentifier encAlgId, AsymmetricKeyParameter publicKey) + { + super(encAlgId); + + this.publicKey = publicKey; + } + + public BcAsymmetricKeyWrapper setSecureRandom(SecureRandom random) + { + this.random = random; + + return this; + } + + public byte[] generateWrappedKey(GenericKey encryptionKey) + throws OperatorException + { + AsymmetricBlockCipher keyEncryptionCipher = createAsymmetricWrapper(getAlgorithmIdentifier().getAlgorithm()); + + CipherParameters params = publicKey; + if (random != null) + { + params = new ParametersWithRandom(params, random); + } + + try + { + byte[] keyEnc = OperatorUtils.getKeyBytes(encryptionKey); + keyEncryptionCipher.init(true, publicKey); + return keyEncryptionCipher.processBlock(keyEnc, 0, keyEnc.length); + } + catch (InvalidCipherTextException e) + { + throw new OperatorException("unable to encrypt contents key", e); + } + } + + protected abstract AsymmetricBlockCipher createAsymmetricWrapper(ASN1ObjectIdentifier algorithm); +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcContentSignerBuilder.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcContentSignerBuilder.java new file mode 100644 index 00000000..7160adff --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcContentSignerBuilder.java @@ -0,0 +1,82 @@ +package org.spongycastle.operator.bc; + +import java.io.OutputStream; +import java.security.SecureRandom; +import java.util.Map; + +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.CryptoException; +import org.spongycastle.crypto.Signer; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.params.ParametersWithRandom; +import org.spongycastle.operator.ContentSigner; +import org.spongycastle.operator.OperatorCreationException; +import org.spongycastle.operator.RuntimeOperatorException; + +public abstract class BcContentSignerBuilder +{ + private SecureRandom random; + private AlgorithmIdentifier sigAlgId; + private AlgorithmIdentifier digAlgId; + + protected BcDigestProvider digestProvider; + + public BcContentSignerBuilder(AlgorithmIdentifier sigAlgId, AlgorithmIdentifier digAlgId) + { + this.sigAlgId = sigAlgId; + this.digAlgId = digAlgId; + this.digestProvider = BcDefaultDigestProvider.INSTANCE; + } + + public BcContentSignerBuilder setSecureRandom(SecureRandom random) + { + this.random = random; + + return this; + } + + public ContentSigner build(AsymmetricKeyParameter privateKey) + throws OperatorCreationException + { + final Signer sig = createSigner(sigAlgId, digAlgId); + + if (random != null) + { + sig.init(true, new ParametersWithRandom(privateKey, random)); + } + else + { + sig.init(true, privateKey); + } + + return new ContentSigner() + { + private BcSignerOutputStream stream = new BcSignerOutputStream(sig); + + public AlgorithmIdentifier getAlgorithmIdentifier() + { + return sigAlgId; + } + + public OutputStream getOutputStream() + { + return stream; + } + + public byte[] getSignature() + { + try + { + return stream.getSignature(); + } + catch (CryptoException e) + { + throw new RuntimeOperatorException("exception obtaining signature: " + e.getMessage(), e); + } + } + }; + } + + protected abstract Signer createSigner(AlgorithmIdentifier sigAlgId, AlgorithmIdentifier algorithmIdentifier) + throws OperatorCreationException; +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcContentVerifierProviderBuilder.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcContentVerifierProviderBuilder.java new file mode 100644 index 00000000..3b975e4f --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcContentVerifierProviderBuilder.java @@ -0,0 +1,144 @@ +package org.spongycastle.operator.bc; + +import java.io.IOException; +import java.io.OutputStream; + +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.cert.X509CertificateHolder; +import org.spongycastle.crypto.Signer; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.operator.ContentVerifier; +import org.spongycastle.operator.ContentVerifierProvider; +import org.spongycastle.operator.OperatorCreationException; + +public abstract class BcContentVerifierProviderBuilder +{ + protected BcDigestProvider digestProvider; + + public BcContentVerifierProviderBuilder() + { + this.digestProvider = BcDefaultDigestProvider.INSTANCE; + } + + public ContentVerifierProvider build(final X509CertificateHolder certHolder) + throws OperatorCreationException + { + return new ContentVerifierProvider() + { + public boolean hasAssociatedCertificate() + { + return true; + } + + public X509CertificateHolder getAssociatedCertificate() + { + return certHolder; + } + + public ContentVerifier get(AlgorithmIdentifier algorithm) + throws OperatorCreationException + { + try + { + AsymmetricKeyParameter publicKey = extractKeyParameters(certHolder.getSubjectPublicKeyInfo()); + BcSignerOutputStream stream = createSignatureStream(algorithm, publicKey); + + return new SigVerifier(algorithm, stream); + } + catch (IOException e) + { + throw new OperatorCreationException("exception on setup: " + e, e); + } + } + }; + } + + public ContentVerifierProvider build(final AsymmetricKeyParameter publicKey) + throws OperatorCreationException + { + return new ContentVerifierProvider() + { + public boolean hasAssociatedCertificate() + { + return false; + } + + public X509CertificateHolder getAssociatedCertificate() + { + return null; + } + + public ContentVerifier get(AlgorithmIdentifier algorithm) + throws OperatorCreationException + { + BcSignerOutputStream stream = createSignatureStream(algorithm, publicKey); + + return new SigVerifier(algorithm, stream); + } + }; + } + + private BcSignerOutputStream createSignatureStream(AlgorithmIdentifier algorithm, AsymmetricKeyParameter publicKey) + throws OperatorCreationException + { + Signer sig = createSigner(algorithm); + + sig.init(false, publicKey); + + return new BcSignerOutputStream(sig); + } + + /** + * Extract an AsymmetricKeyParameter from the passed in SubjectPublicKeyInfo structure. + * + * @param publicKeyInfo a publicKeyInfo structure describing the public key required. + * @return an AsymmetricKeyParameter object containing the appropriate public key. + * @throws IOException if the publicKeyInfo data cannot be parsed, + */ + protected abstract AsymmetricKeyParameter extractKeyParameters(SubjectPublicKeyInfo publicKeyInfo) + throws IOException; + + /** + * Create the correct signer for the algorithm identifier sigAlgId. + * + * @param sigAlgId the algorithm details for the signature we want to verify. + * @return a Signer object. + * @throws OperatorCreationException if the Signer cannot be constructed. + */ + protected abstract Signer createSigner(AlgorithmIdentifier sigAlgId) + throws OperatorCreationException; + + private class SigVerifier + implements ContentVerifier + { + private BcSignerOutputStream stream; + private AlgorithmIdentifier algorithm; + + SigVerifier(AlgorithmIdentifier algorithm, BcSignerOutputStream stream) + { + this.algorithm = algorithm; + this.stream = stream; + } + + public AlgorithmIdentifier getAlgorithmIdentifier() + { + return algorithm; + } + + public OutputStream getOutputStream() + { + if (stream == null) + { + throw new IllegalStateException("verifier not initialised"); + } + + return stream; + } + + public boolean verify(byte[] expected) + { + return stream.verify(expected); + } + } +}
\ No newline at end of file diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcDSAContentSignerBuilder.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcDSAContentSignerBuilder.java new file mode 100644 index 00000000..db7b608d --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcDSAContentSignerBuilder.java @@ -0,0 +1,25 @@ +package org.spongycastle.operator.bc; + +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.Signer; +import org.spongycastle.crypto.signers.DSADigestSigner; +import org.spongycastle.crypto.signers.DSASigner; +import org.spongycastle.operator.OperatorCreationException; + +public class BcDSAContentSignerBuilder + extends BcContentSignerBuilder +{ + public BcDSAContentSignerBuilder(AlgorithmIdentifier sigAlgId, AlgorithmIdentifier digAlgId) + { + super(sigAlgId, digAlgId); + } + + protected Signer createSigner(AlgorithmIdentifier sigAlgId, AlgorithmIdentifier digAlgId) + throws OperatorCreationException + { + Digest dig = digestProvider.get(digAlgId); + + return new DSADigestSigner(new DSASigner(), dig); + } +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcDSAContentVerifierProviderBuilder.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcDSAContentVerifierProviderBuilder.java new file mode 100644 index 00000000..aaf25f4d --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcDSAContentVerifierProviderBuilder.java @@ -0,0 +1,40 @@ +package org.spongycastle.operator.bc; + +import java.io.IOException; + +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.Signer; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.signers.DSADigestSigner; +import org.spongycastle.crypto.signers.DSASigner; +import org.spongycastle.crypto.util.PublicKeyFactory; +import org.spongycastle.operator.DigestAlgorithmIdentifierFinder; +import org.spongycastle.operator.OperatorCreationException; + +public class BcDSAContentVerifierProviderBuilder + extends BcContentVerifierProviderBuilder +{ + private DigestAlgorithmIdentifierFinder digestAlgorithmFinder; + + public BcDSAContentVerifierProviderBuilder(DigestAlgorithmIdentifierFinder digestAlgorithmFinder) + { + this.digestAlgorithmFinder = digestAlgorithmFinder; + } + + protected Signer createSigner(AlgorithmIdentifier sigAlgId) + throws OperatorCreationException + { + AlgorithmIdentifier digAlg = digestAlgorithmFinder.find(sigAlgId); + Digest dig = digestProvider.get(digAlg); + + return new DSADigestSigner(new DSASigner(), dig); + } + + protected AsymmetricKeyParameter extractKeyParameters(SubjectPublicKeyInfo publicKeyInfo) + throws IOException + { + return PublicKeyFactory.createKey(publicKeyInfo); + } +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcDefaultDigestProvider.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcDefaultDigestProvider.java new file mode 100644 index 00000000..dce50a9e --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcDefaultDigestProvider.java @@ -0,0 +1,144 @@ +package org.spongycastle.operator.bc; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.spongycastle.asn1.cryptopro.CryptoProObjectIdentifiers; +import org.spongycastle.asn1.nist.NISTObjectIdentifiers; +import org.spongycastle.asn1.oiw.OIWObjectIdentifiers; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.ExtendedDigest; +import org.spongycastle.crypto.digests.GOST3411Digest; +import org.spongycastle.crypto.digests.MD2Digest; +import org.spongycastle.crypto.digests.MD4Digest; +import org.spongycastle.crypto.digests.MD5Digest; +import org.spongycastle.crypto.digests.RIPEMD128Digest; +import org.spongycastle.crypto.digests.RIPEMD160Digest; +import org.spongycastle.crypto.digests.RIPEMD256Digest; +import org.spongycastle.crypto.digests.SHA1Digest; +import org.spongycastle.crypto.digests.SHA224Digest; +import org.spongycastle.crypto.digests.SHA256Digest; +import org.spongycastle.crypto.digests.SHA384Digest; +import org.spongycastle.crypto.digests.SHA512Digest; +import org.spongycastle.operator.OperatorCreationException; + +public class BcDefaultDigestProvider + implements BcDigestProvider +{ + private static final Map lookup = createTable(); + + private static Map createTable() + { + Map table = new HashMap(); + + table.put(OIWObjectIdentifiers.idSHA1, new BcDigestProvider() + { + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + { + return new SHA1Digest(); + } + }); + table.put(NISTObjectIdentifiers.id_sha224, new BcDigestProvider() + { + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + { + return new SHA224Digest(); + } + }); + table.put(NISTObjectIdentifiers.id_sha256, new BcDigestProvider() + { + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + { + return new SHA256Digest(); + } + }); + table.put(NISTObjectIdentifiers.id_sha384, new BcDigestProvider() + { + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + { + return new SHA384Digest(); + } + }); + table.put(NISTObjectIdentifiers.id_sha512, new BcDigestProvider() + { + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + { + return new SHA512Digest(); + } + }); + table.put(PKCSObjectIdentifiers.md5, new BcDigestProvider() + { + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + { + return new MD5Digest(); + } + }); + table.put(PKCSObjectIdentifiers.md4, new BcDigestProvider() + { + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + { + return new MD4Digest(); + } + }); + table.put(PKCSObjectIdentifiers.md2, new BcDigestProvider() + { + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + { + return new MD2Digest(); + } + }); + table.put(CryptoProObjectIdentifiers.gostR3411, new BcDigestProvider() + { + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + { + return new GOST3411Digest(); + } + }); + table.put(TeleTrusTObjectIdentifiers.ripemd128, new BcDigestProvider() + { + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + { + return new RIPEMD128Digest(); + } + }); + table.put(TeleTrusTObjectIdentifiers.ripemd160, new BcDigestProvider() + { + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + { + return new RIPEMD160Digest(); + } + }); + table.put(TeleTrusTObjectIdentifiers.ripemd256, new BcDigestProvider() + { + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + { + return new RIPEMD256Digest(); + } + }); + + return Collections.unmodifiableMap(table); + } + + public static final BcDigestProvider INSTANCE = new BcDefaultDigestProvider(); + + private BcDefaultDigestProvider() + { + + } + + public ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + throws OperatorCreationException + { + BcDigestProvider extProv = (BcDigestProvider)lookup.get(digestAlgorithmIdentifier.getAlgorithm()); + + if (extProv == null) + { + throw new OperatorCreationException("cannot recognise digest"); + } + + return extProv.get(digestAlgorithmIdentifier); + } +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcDigestCalculatorProvider.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcDigestCalculatorProvider.java new file mode 100644 index 00000000..8e0a12f6 --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcDigestCalculatorProvider.java @@ -0,0 +1,82 @@ +package org.spongycastle.operator.bc; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; + +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.ExtendedDigest; +import org.spongycastle.operator.DigestCalculator; +import org.spongycastle.operator.DigestCalculatorProvider; +import org.spongycastle.operator.OperatorCreationException; + +public class BcDigestCalculatorProvider + implements DigestCalculatorProvider +{ + private BcDigestProvider digestProvider = BcDefaultDigestProvider.INSTANCE; + + public DigestCalculator get(final AlgorithmIdentifier algorithm) + throws OperatorCreationException + { + Digest dig = digestProvider.get(algorithm); + + final DigestOutputStream stream = new DigestOutputStream(dig); + + return new DigestCalculator() + { + public AlgorithmIdentifier getAlgorithmIdentifier() + { + return algorithm; + } + + public OutputStream getOutputStream() + { + return stream; + } + + public byte[] getDigest() + { + return stream.getDigest(); + } + }; + } + + private class DigestOutputStream + extends OutputStream + { + private Digest dig; + + DigestOutputStream(Digest dig) + { + this.dig = dig; + } + + public void write(byte[] bytes, int off, int len) + throws IOException + { + dig.update(bytes, off, len); + } + + public void write(byte[] bytes) + throws IOException + { + dig.update(bytes, 0, bytes.length); + } + + public void write(int b) + throws IOException + { + dig.update((byte)b); + } + + byte[] getDigest() + { + byte[] d = new byte[dig.getDigestSize()]; + + dig.doFinal(d, 0); + + return d; + } + } +}
\ No newline at end of file diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcDigestProvider.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcDigestProvider.java new file mode 100644 index 00000000..6eb930ee --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcDigestProvider.java @@ -0,0 +1,11 @@ +package org.spongycastle.operator.bc; + +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.ExtendedDigest; +import org.spongycastle.operator.OperatorCreationException; + +public interface BcDigestProvider +{ + ExtendedDigest get(AlgorithmIdentifier digestAlgorithmIdentifier) + throws OperatorCreationException; +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcRSAAsymmetricKeyUnwrapper.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcRSAAsymmetricKeyUnwrapper.java new file mode 100644 index 00000000..99762353 --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcRSAAsymmetricKeyUnwrapper.java @@ -0,0 +1,22 @@ +package org.spongycastle.operator.bc; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.AsymmetricBlockCipher; +import org.spongycastle.crypto.encodings.PKCS1Encoding; +import org.spongycastle.crypto.engines.RSAEngine; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; + +public class BcRSAAsymmetricKeyUnwrapper + extends BcAsymmetricKeyUnwrapper +{ + public BcRSAAsymmetricKeyUnwrapper(AlgorithmIdentifier encAlgId, AsymmetricKeyParameter privateKey) + { + super(encAlgId, privateKey); + } + + protected AsymmetricBlockCipher createAsymmetricUnwrapper(ASN1ObjectIdentifier algorithm) + { + return new PKCS1Encoding(new RSAEngine()); + } +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcRSAAsymmetricKeyWrapper.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcRSAAsymmetricKeyWrapper.java new file mode 100644 index 00000000..c2153e6d --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcRSAAsymmetricKeyWrapper.java @@ -0,0 +1,32 @@ +package org.spongycastle.operator.bc; + +import java.io.IOException; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.crypto.AsymmetricBlockCipher; +import org.spongycastle.crypto.encodings.PKCS1Encoding; +import org.spongycastle.crypto.engines.RSAEngine; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.util.PublicKeyFactory; + +public class BcRSAAsymmetricKeyWrapper + extends BcAsymmetricKeyWrapper +{ + public BcRSAAsymmetricKeyWrapper(AlgorithmIdentifier encAlgId, AsymmetricKeyParameter publicKey) + { + super(encAlgId, publicKey); + } + + public BcRSAAsymmetricKeyWrapper(AlgorithmIdentifier encAlgId, SubjectPublicKeyInfo publicKeyInfo) + throws IOException + { + super(encAlgId, PublicKeyFactory.createKey(publicKeyInfo)); + } + + protected AsymmetricBlockCipher createAsymmetricWrapper(ASN1ObjectIdentifier algorithm) + { + return new PKCS1Encoding(new RSAEngine()); + } +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcRSAContentSignerBuilder.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcRSAContentSignerBuilder.java new file mode 100644 index 00000000..d62543b0 --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcRSAContentSignerBuilder.java @@ -0,0 +1,24 @@ +package org.spongycastle.operator.bc; + +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.Signer; +import org.spongycastle.crypto.signers.RSADigestSigner; +import org.spongycastle.operator.OperatorCreationException; + +public class BcRSAContentSignerBuilder + extends BcContentSignerBuilder +{ + public BcRSAContentSignerBuilder(AlgorithmIdentifier sigAlgId, AlgorithmIdentifier digAlgId) + { + super(sigAlgId, digAlgId); + } + + protected Signer createSigner(AlgorithmIdentifier sigAlgId, AlgorithmIdentifier digAlgId) + throws OperatorCreationException + { + Digest dig = digestProvider.get(digAlgId); + + return new RSADigestSigner(dig); + } +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcRSAContentVerifierProviderBuilder.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcRSAContentVerifierProviderBuilder.java new file mode 100644 index 00000000..e1fd6736 --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcRSAContentVerifierProviderBuilder.java @@ -0,0 +1,39 @@ +package org.spongycastle.operator.bc; + +import java.io.IOException; + +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.crypto.Digest; +import org.spongycastle.crypto.Signer; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.signers.RSADigestSigner; +import org.spongycastle.crypto.util.PublicKeyFactory; +import org.spongycastle.operator.DigestAlgorithmIdentifierFinder; +import org.spongycastle.operator.OperatorCreationException; + +public class BcRSAContentVerifierProviderBuilder + extends BcContentVerifierProviderBuilder +{ + private DigestAlgorithmIdentifierFinder digestAlgorithmFinder; + + public BcRSAContentVerifierProviderBuilder(DigestAlgorithmIdentifierFinder digestAlgorithmFinder) + { + this.digestAlgorithmFinder = digestAlgorithmFinder; + } + + protected Signer createSigner(AlgorithmIdentifier sigAlgId) + throws OperatorCreationException + { + AlgorithmIdentifier digAlg = digestAlgorithmFinder.find(sigAlgId); + Digest dig = digestProvider.get(digAlg); + + return new RSADigestSigner(dig); + } + + protected AsymmetricKeyParameter extractKeyParameters(SubjectPublicKeyInfo publicKeyInfo) + throws IOException + { + return PublicKeyFactory.createKey(publicKeyInfo); + } +}
\ No newline at end of file diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcSignerOutputStream.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcSignerOutputStream.java new file mode 100644 index 00000000..f4cdf62b --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcSignerOutputStream.java @@ -0,0 +1,47 @@ +package org.spongycastle.operator.bc; + +import java.io.IOException; +import java.io.OutputStream; + +import org.spongycastle.crypto.CryptoException; +import org.spongycastle.crypto.Signer; + +public class BcSignerOutputStream + extends OutputStream +{ + private Signer sig; + + BcSignerOutputStream(Signer sig) + { + this.sig = sig; + } + + public void write(byte[] bytes, int off, int len) + throws IOException + { + sig.update(bytes, off, len); + } + + public void write(byte[] bytes) + throws IOException + { + sig.update(bytes, 0, bytes.length); + } + + public void write(int b) + throws IOException + { + sig.update((byte)b); + } + + byte[] getSignature() + throws CryptoException + { + return sig.generateSignature(); + } + + boolean verify(byte[] expected) + { + return sig.verifySignature(expected); + } +}
\ No newline at end of file diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcSymmetricKeyUnwrapper.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcSymmetricKeyUnwrapper.java new file mode 100644 index 00000000..da37cf1a --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcSymmetricKeyUnwrapper.java @@ -0,0 +1,49 @@ +package org.spongycastle.operator.bc; + +import java.security.SecureRandom; + +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.InvalidCipherTextException; +import org.spongycastle.crypto.Wrapper; +import org.spongycastle.crypto.params.KeyParameter; +import org.spongycastle.operator.GenericKey; +import org.spongycastle.operator.OperatorException; +import org.spongycastle.operator.SymmetricKeyUnwrapper; + +public class BcSymmetricKeyUnwrapper + extends SymmetricKeyUnwrapper +{ + private SecureRandom random; + private Wrapper wrapper; + private KeyParameter wrappingKey; + + public BcSymmetricKeyUnwrapper(AlgorithmIdentifier wrappingAlgorithm, Wrapper wrapper, KeyParameter wrappingKey) + { + super(wrappingAlgorithm); + + this.wrapper = wrapper; + this.wrappingKey = wrappingKey; + } + + public BcSymmetricKeyUnwrapper setSecureRandom(SecureRandom random) + { + this.random = random; + + return this; + } + + public GenericKey generateUnwrappedKey(AlgorithmIdentifier encryptedKeyAlgorithm, byte[] encryptedKey) + throws OperatorException + { + wrapper.init(false, wrappingKey); + + try + { + return new GenericKey(encryptedKeyAlgorithm, wrapper.unwrap(encryptedKey, 0, encryptedKey.length)); + } + catch (InvalidCipherTextException e) + { + throw new OperatorException("unable to unwrap key: " + e.getMessage(), e); + } + } +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/BcSymmetricKeyWrapper.java b/pkix/src/main/java/org/spongycastle/operator/bc/BcSymmetricKeyWrapper.java new file mode 100644 index 00000000..a35de7d7 --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/BcSymmetricKeyWrapper.java @@ -0,0 +1,51 @@ +package org.spongycastle.operator.bc; + +import java.security.SecureRandom; + +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.Wrapper; +import org.spongycastle.crypto.params.KeyParameter; +import org.spongycastle.crypto.params.ParametersWithRandom; +import org.spongycastle.operator.GenericKey; +import org.spongycastle.operator.OperatorException; +import org.spongycastle.operator.SymmetricKeyWrapper; + +public class BcSymmetricKeyWrapper + extends SymmetricKeyWrapper +{ + private SecureRandom random; + private Wrapper wrapper; + private KeyParameter wrappingKey; + + public BcSymmetricKeyWrapper(AlgorithmIdentifier wrappingAlgorithm, Wrapper wrapper, KeyParameter wrappingKey) + { + super(wrappingAlgorithm); + + this.wrapper = wrapper; + this.wrappingKey = wrappingKey; + } + + public BcSymmetricKeyWrapper setSecureRandom(SecureRandom random) + { + this.random = random; + + return this; + } + + public byte[] generateWrappedKey(GenericKey encryptionKey) + throws OperatorException + { + byte[] contentEncryptionKeySpec = OperatorUtils.getKeyBytes(encryptionKey); + + if (random == null) + { + wrapper.init(true, wrappingKey); + } + else + { + wrapper.init(true, new ParametersWithRandom(wrappingKey, random)); + } + + return wrapper.wrap(contentEncryptionKeySpec, 0, contentEncryptionKeySpec.length); + } +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/CamelliaUtil.java b/pkix/src/main/java/org/spongycastle/operator/bc/CamelliaUtil.java new file mode 100644 index 00000000..9b7c9836 --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/CamelliaUtil.java @@ -0,0 +1,36 @@ +package org.spongycastle.operator.bc; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ntt.NTTObjectIdentifiers; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.crypto.params.KeyParameter; + +class CamelliaUtil +{ + static AlgorithmIdentifier determineKeyEncAlg(KeyParameter key) + { + int length = key.getKey().length * 8; + ASN1ObjectIdentifier wrapOid; + + if (length == 128) + { + wrapOid = NTTObjectIdentifiers.id_camellia128_wrap; + } + else if (length == 192) + { + wrapOid = NTTObjectIdentifiers.id_camellia192_wrap; + } + else if (length == 256) + { + wrapOid = NTTObjectIdentifiers.id_camellia256_wrap; + } + else + { + throw new IllegalArgumentException( + "illegal keysize in Camellia"); + } + + return new AlgorithmIdentifier(wrapOid); // parameters must be + // absent + } +} diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/OperatorUtils.java b/pkix/src/main/java/org/spongycastle/operator/bc/OperatorUtils.java new file mode 100644 index 00000000..a53c4692 --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/OperatorUtils.java @@ -0,0 +1,23 @@ +package org.spongycastle.operator.bc; + +import java.security.Key; + +import org.spongycastle.operator.GenericKey; + +class OperatorUtils +{ + static byte[] getKeyBytes(GenericKey key) + { + if (key.getRepresentation() instanceof Key) + { + return ((Key)key.getRepresentation()).getEncoded(); + } + + if (key.getRepresentation() instanceof byte[]) + { + return (byte[])key.getRepresentation(); + } + + throw new IllegalArgumentException("unknown generic key type"); + } +}
\ No newline at end of file diff --git a/pkix/src/main/java/org/spongycastle/operator/bc/SEEDUtil.java b/pkix/src/main/java/org/spongycastle/operator/bc/SEEDUtil.java new file mode 100644 index 00000000..4d977310 --- /dev/null +++ b/pkix/src/main/java/org/spongycastle/operator/bc/SEEDUtil.java @@ -0,0 +1,14 @@ +package org.spongycastle.operator.bc; + +import org.spongycastle.asn1.kisa.KISAObjectIdentifiers; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; + +class SEEDUtil +{ + static AlgorithmIdentifier determineKeyEncAlg() + { + // parameters absent + return new AlgorithmIdentifier( + KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap); + } +} |