From 728acd760f49a291d97087b40a2c65c7951eec0f Mon Sep 17 00:00:00 2001 From: David Hook Date: Mon, 30 Dec 2024 17:28:11 +1100 Subject: [PATCH] Java 4 updates --- .../crypto/threshold/ShamirSplitSecret.java | 4 +- .../crypto/engines/AsconAEAD128.java | 206 +++++ .../crypto/engines/AsconBaseEngine.java | 516 +++++++++++ .../crypto/threshold/Polynomial.java | 287 ++++++ .../threshold/ShamirSecretSplitter.java | 153 ++++ .../crypto/threshold/ShamirSplitSecret.java | 91 ++ .../asn1/test/ObjectIdentifierTest.java | 2 +- .../test/ShamirSecretSplitterTest.java | 32 +- .../org/bouncycastle/bcpg/KeyIdentifier.java | 4 +- .../openpgp/PGPEncryptedDataGenerator.java | 2 +- .../PGPSignatureSubpacketGenerator.java | 4 +- .../openpgp/api/OpenPGPV6KeyGenerator.java | 9 +- .../api/test/OpenPGPV6KeyGeneratorTest.java | 77 +- .../openpgp/test/OperatorBcTest.java | 14 +- .../openpgp/test/PGPKeyPairGeneratorTest.java | 100 +-- .../openpgp/test/PGPv6KeyTest.java | 8 +- .../cms/jcajce/CMSInputAEADDecryptor.java | 28 +- .../cms/jcajce/CMSInputAEADDecryptor.java | 54 ++ .../cms/test/NewSignedDataTest.java | 2 +- .../cms/test/PQCSignedDataTest.java | 445 ++++++++++ .../bouncycastle/cms/test/PQCTestUtil.java | 132 +++ .../compositesignatures/KeyFactorySpi.java | 91 +- .../pqc/jcajce/provider/util/WrapUtil.java | 2 +- .../asymmetric/ec/BCECPrivateKey.java | 94 +- .../ecgost/BCECGOST3410PrivateKey.java | 110 +-- .../symmetric/util/BaseBlockCipher.java | 154 +++- .../jce/provider/test/PBETest.java | 824 ++++++++++++++++++ .../tls/test/TestAEADNonceGenerator.java | 3 +- 28 files changed, 3180 insertions(+), 268 deletions(-) create mode 100644 core/src/main/jdk1.4/org/bouncycastle/crypto/engines/AsconAEAD128.java create mode 100644 core/src/main/jdk1.4/org/bouncycastle/crypto/engines/AsconBaseEngine.java create mode 100644 core/src/main/jdk1.4/org/bouncycastle/crypto/threshold/Polynomial.java create mode 100644 core/src/main/jdk1.4/org/bouncycastle/crypto/threshold/ShamirSecretSplitter.java create mode 100644 core/src/main/jdk1.4/org/bouncycastle/crypto/threshold/ShamirSplitSecret.java create mode 100644 pkix/src/main/jdk1.4/org/bouncycastle/cms/jcajce/CMSInputAEADDecryptor.java create mode 100644 pkix/src/test/jdk1.4/org/bouncycastle/cms/test/PQCSignedDataTest.java create mode 100644 pkix/src/test/jdk1.4/org/bouncycastle/cms/test/PQCTestUtil.java create mode 100644 prov/src/test/jdk1.4/org/bouncycastle/jce/provider/test/PBETest.java diff --git a/core/src/main/java/org/bouncycastle/crypto/threshold/ShamirSplitSecret.java b/core/src/main/java/org/bouncycastle/crypto/threshold/ShamirSplitSecret.java index 0e79476353..59b2a7a66d 100644 --- a/core/src/main/java/org/bouncycastle/crypto/threshold/ShamirSplitSecret.java +++ b/core/src/main/java/org/bouncycastle/crypto/threshold/ShamirSplitSecret.java @@ -79,9 +79,9 @@ public byte[] getSecret() } tmp = 1; - for (byte p : products) + for (int prdI = 0; prdI != products.length; prdI++) { - tmp = poly.gfMul(tmp & 0xff, p & 0xff); + tmp = poly.gfMul(tmp & 0xff, products[prdI] & 0xff); } r[i] = tmp; } diff --git a/core/src/main/jdk1.4/org/bouncycastle/crypto/engines/AsconAEAD128.java b/core/src/main/jdk1.4/org/bouncycastle/crypto/engines/AsconAEAD128.java new file mode 100644 index 0000000000..409f136095 --- /dev/null +++ b/core/src/main/jdk1.4/org/bouncycastle/crypto/engines/AsconAEAD128.java @@ -0,0 +1,206 @@ +package org.bouncycastle.crypto.engines; + +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.CryptoServicesRegistrar; +import org.bouncycastle.crypto.constraints.DefaultServiceProperties; +import org.bouncycastle.crypto.params.AEADParameters; +import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.crypto.params.ParametersWithIV; +import org.bouncycastle.util.Pack; + +/** + * Ascon-AEAD128 was introduced as part of the NIST Lightweight Cryptography + * competition and described in the NIST Special Publication SP 800-232 (Initial + * Public Draft). + * For additional details, see: + * + * + * @version 1.3 + */ +public class AsconAEAD128 + extends AsconBaseEngine +{ + public AsconAEAD128() + { + CRYPTO_KEYBYTES = 16; + CRYPTO_ABYTES = 16; + ASCON_AEAD_RATE = 16; + ASCON_IV = 0x00001000808c0001L; + algorithmName = "Ascon-AEAD128"; + nr = 8; + m_bufferSizeDecrypt = ASCON_AEAD_RATE + CRYPTO_ABYTES; + m_buf = new byte[m_bufferSizeDecrypt]; + dsep = -9223372036854775808L; //0x80L << 56 + } + + protected long pad(int i) + { + return 0x01L << (i << 3); + } + + @Override + protected long loadBytes(byte[] in, int inOff) + { + return Pack.littleEndianToLong(in, inOff); + } + + @Override + protected void setBytes(long n, byte[] bs, int off) + { + Pack.longToLittleEndian(n, bs, off); + } + + protected void ascon_aeadinit() + { + /* initialize */ + x0 = ASCON_IV; + x1 = K0; + x2 = K1; + x3 = N0; + x4 = N1; + p(12); + x3 ^= K0; + x4 ^= K1; + } + + protected void processFinalAadBlock() + { + if (m_bufPos >= 8) // ASCON_AEAD_RATE == 16 is implied + { + x0 ^= Pack.littleEndianToLong(m_buf, 0); + x1 ^= Pack.littleEndianToLong(m_buf, 8) ^ pad(m_bufPos); + } + else + { + x0 ^= Pack.littleEndianToLong(m_buf, 0) ^ pad(m_bufPos); + } + } + + protected void processFinalDecrypt(byte[] input, int inLen, byte[] output, int outOff) + { + if (inLen >= 8) // ASCON_AEAD_RATE == 16 is implied + { + long c0 = Pack.littleEndianToLong(input, 0); + inLen -= 8; + long c1 = Pack.littleEndianToLong(input, 8, inLen); + Pack.longToLittleEndian(x0 ^ c0, output, outOff); + Pack.longToLittleEndian(x1 ^ c1, output, outOff + 8, inLen); + x0 = c0; + x1 &= -(1L << (inLen << 3)); + x1 |= c1; + x1 ^= pad(inLen); + } + else + { + if (inLen != 0) + { + long c0 = Pack.littleEndianToLong(input, 0, inLen); + Pack.longToLittleEndian(x0 ^ c0, output, outOff, inLen); + x0 &= -(1L << (inLen << 3)); + x0 |= c0; + } + x0 ^= pad(inLen); + } + finishData(DecFinal); + } + + protected void processFinalEncrypt(byte[] input, int inLen, byte[] output, int outOff) + { + if (inLen >= 8) // ASCON_AEAD_RATE == 16 is implied + { + x0 ^= Pack.littleEndianToLong(input, 0); + inLen -= 8; + x1 ^= Pack.littleEndianToLong(input, 8, inLen); + Pack.longToLittleEndian(x0, output, outOff); + Pack.longToLittleEndian(x1, output, outOff + 8); + x1 ^= pad(inLen); + } + else + { + if (inLen != 0) + { + x0 ^= Pack.littleEndianToLong(input, 0, inLen); + Pack.longToLittleEndian(x0, output, outOff, inLen); + } + x0 ^= pad(inLen); + } + finishData(EncFinal); + } + + private void finishData(State nextState) + { + x2 ^= K0; + x3 ^= K1; + p(12); + x3 ^= K0; + x4 ^= K1; + m_state = nextState; + } + + public void init(boolean forEncryption, CipherParameters params) + throws IllegalArgumentException + { + KeyParameter key; + byte[] npub; + if (params instanceof AEADParameters) + { + AEADParameters aeadParameters = (AEADParameters)params; + key = aeadParameters.getKey(); + npub = aeadParameters.getNonce(); + initialAssociatedText = aeadParameters.getAssociatedText(); + + int macSizeBits = aeadParameters.getMacSize(); + if (macSizeBits != CRYPTO_ABYTES * 8) + { + throw new IllegalArgumentException("Invalid value for MAC size: " + macSizeBits); + } + } + else if (params instanceof ParametersWithIV) + { + ParametersWithIV withIV = (ParametersWithIV)params; + key = (KeyParameter)withIV.getParameters(); + npub = withIV.getIV(); + initialAssociatedText = null; + } + else + { + throw new IllegalArgumentException("invalid parameters passed to Ascon"); + } + + if (key == null) + { + throw new IllegalArgumentException("Ascon Init parameters must include a key"); + } + if (npub == null || npub.length != CRYPTO_ABYTES) + { + throw new IllegalArgumentException("Ascon-AEAD-128 requires exactly " + CRYPTO_ABYTES + " bytes of IV"); + } + + byte[] k = key.getKey(); + if (k.length != CRYPTO_KEYBYTES) + { + throw new IllegalArgumentException("Ascon-AEAD-128 key must be " + CRYPTO_KEYBYTES + " bytes long"); + } + + CryptoServicesRegistrar.checkConstraints(new DefaultServiceProperties( + this.getAlgorithmName(), 128, params, Utils.getPurpose(forEncryption))); + K0 = Pack.littleEndianToLong(k, 0); + K1 = Pack.littleEndianToLong(k, 8); + N0 = Pack.littleEndianToLong(npub, 0); + N1 = Pack.littleEndianToLong(npub, 8); + + m_state = forEncryption ? EncInit : DecInit; + + reset(true); + } + + public String getAlgorithmVersion() + { + return "v1.3"; + } +} + diff --git a/core/src/main/jdk1.4/org/bouncycastle/crypto/engines/AsconBaseEngine.java b/core/src/main/jdk1.4/org/bouncycastle/crypto/engines/AsconBaseEngine.java new file mode 100644 index 0000000000..347e426025 --- /dev/null +++ b/core/src/main/jdk1.4/org/bouncycastle/crypto/engines/AsconBaseEngine.java @@ -0,0 +1,516 @@ +package org.bouncycastle.crypto.engines; + +import org.bouncycastle.crypto.DataLengthException; +import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.crypto.OutputLengthException; +import org.bouncycastle.crypto.modes.AEADCipher; +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Longs; + +abstract class AsconBaseEngine + implements AEADCipher +{ + protected static final int UNINITIALIZED = 0; + protected static final int ENCINIT = 1; + protected static final int ENCAAD = 2; + protected static final int ENCDATA = 3; + protected static final int ENCFINAL = 4; + protected static final int DECINIT = 5; + protected static final int DECAAD = 6; + protected static final int DECDATA = 7; + protected static final int DECFINAL = 8; + + protected static final State Uninitialized = new State(UNINITIALIZED); + protected static final State EncInit = new State(ENCINIT); + protected static final State EncAad = new State(ENCAAD); + protected static final State EncData = new State(ENCDATA); + protected static final State EncFinal = new State(ENCFINAL); + protected static final State DecInit = new State(DECINIT); + protected static final State DecAad = new State(DECAAD); + protected static final State DecData = new State(DECDATA); + protected static final State DecFinal = new State(DECFINAL); + + protected static class State + { + int ord; + + private State(int ord) + { + this.ord = ord; + } + } + + protected State m_state = Uninitialized; + protected String algorithmName; + protected byte[] mac; + protected byte[] initialAssociatedText; + protected int CRYPTO_KEYBYTES; + protected int CRYPTO_ABYTES; + protected int nr; + protected int ASCON_AEAD_RATE; + protected long K0; + protected long K1; + protected long N0; + protected long N1; + protected long ASCON_IV; + protected long x0; + protected long x1; + protected long x2; + protected long x3; + protected long x4; + protected int m_bufferSizeDecrypt; + protected byte[] m_buf; + protected int m_bufPos = 0; + protected long dsep; //domain separation + + protected abstract long pad(int i); + + protected abstract long loadBytes(byte[] in, int inOff); + + protected abstract void setBytes(long n, byte[] bs, int off); + + private void round(long C) + { + long t0 = x0 ^ x1 ^ x2 ^ x3 ^ C ^ (x1 & (x0 ^ x2 ^ x4 ^ C)); + long t1 = x0 ^ x2 ^ x3 ^ x4 ^ C ^ ((x1 ^ x2 ^ C) & (x1 ^ x3)); + long t2 = x1 ^ x2 ^ x4 ^ C ^ (x3 & x4); + long t3 = x0 ^ x1 ^ x2 ^ C ^ ((~x0) & (x3 ^ x4)); + long t4 = x1 ^ x3 ^ x4 ^ ((x0 ^ x4) & x1); + x0 = t0 ^ Longs.rotateRight(t0, 19) ^ Longs.rotateRight(t0, 28); + x1 = t1 ^ Longs.rotateRight(t1, 39) ^ Longs.rotateRight(t1, 61); + x2 = ~(t2 ^ Longs.rotateRight(t2, 1) ^ Longs.rotateRight(t2, 6)); + x3 = t3 ^ Longs.rotateRight(t3, 10) ^ Longs.rotateRight(t3, 17); + x4 = t4 ^ Longs.rotateRight(t4, 7) ^ Longs.rotateRight(t4, 41); + } + + protected void p(int nr) + { + if (nr == 12) + { + round(0xf0L); + round(0xe1L); + round(0xd2L); + round(0xc3L); + } + if (nr >= 8) + { + round(0xb4L); + round(0xa5L); + } + round(0x96L); + round(0x87L); + round(0x78L); + round(0x69L); + round(0x5aL); + round(0x4bL); + } + + protected abstract void ascon_aeadinit(); + + protected void checkAAD() + { + switch (m_state.ord) + { + case DECINIT: + m_state = DecAad; + break; + case ENCINIT: + m_state = EncAad; + break; + case DECAAD: + case ENCAAD: + break; + case ENCFINAL: + throw new IllegalStateException(getAlgorithmName() + " cannot be reused for encryption"); + default: + throw new IllegalStateException(getAlgorithmName() + " needs to be initialized"); + } + } + + protected boolean checkData() + { + switch (m_state.ord) + { + case DECINIT: + case DECAAD: + finishAAD(DecData); + return false; + case ENCINIT: + case ENCAAD: + finishAAD(EncData); + return true; + case DECDATA: + return false; + case ENCDATA: + return true; + case ENCFINAL: + throw new IllegalStateException(getAlgorithmName() + " cannot be reused for encryption"); + default: + throw new IllegalStateException(getAlgorithmName() + " needs to be initialized"); + } + } + + private void finishAAD(State nextState) + { + // State indicates whether we ever received AAD + switch (m_state.ord) + { + case DECAAD: + case ENCAAD: + processFinalAadBlock(); + p(nr); + break; + default: + break; + } + // domain separation + x4 ^= dsep; + m_bufPos = 0; + m_state = nextState; + } + + protected abstract void processFinalAadBlock(); + + protected abstract void processFinalDecrypt(byte[] input, int inLen, byte[] output, int outOff); + + protected abstract void processFinalEncrypt(byte[] input, int inLen, byte[] output, int outOff); + + protected void processBufferAAD(byte[] buffer, int inOff) + { + x0 ^= loadBytes(buffer, inOff); + if (ASCON_AEAD_RATE == 16) + { + x1 ^= loadBytes(buffer, 8 + inOff); + } + p(nr); + } + + + protected void processBufferDecrypt(byte[] buffer, int bufOff, byte[] output, int outOff) + { + if (outOff + ASCON_AEAD_RATE > output.length) + { + throw new OutputLengthException("output buffer too short"); + } + long t0 = loadBytes(buffer, bufOff); + setBytes(x0 ^ t0, output, outOff); + x0 = t0; + + if (ASCON_AEAD_RATE == 16) + { + long t1 = loadBytes(buffer, bufOff + 8); + setBytes(x1 ^ t1, output, outOff + 8); + x1 = t1; + } + p(nr); + } + + protected void processBufferEncrypt(byte[] buffer, int bufOff, byte[] output, int outOff) + { + if (outOff + ASCON_AEAD_RATE > output.length) + { + throw new OutputLengthException("output buffer too short"); + } + x0 ^= loadBytes(buffer, bufOff); + setBytes(x0, output, outOff); + + if (ASCON_AEAD_RATE == 16) + { + x1 ^= loadBytes(buffer, bufOff + 8); + setBytes(x1, output, outOff + 8); + } + p(nr); + } + + public void processAADByte(byte in) + { + checkAAD(); + m_buf[m_bufPos] = in; + if (++m_bufPos == ASCON_AEAD_RATE) + { + processBufferAAD(m_buf, 0); + m_bufPos = 0; + } + } + + public void processAADBytes(byte[] inBytes, int inOff, int len) + { + if ((inOff + len) > inBytes.length) + { + throw new DataLengthException("input buffer too short"); + } + // Don't enter AAD state until we actually get input + if (len <= 0) + { + return; + } + checkAAD(); + if (m_bufPos > 0) + { + int available = ASCON_AEAD_RATE - m_bufPos; + if (len < available) + { + System.arraycopy(inBytes, inOff, m_buf, m_bufPos, len); + m_bufPos += len; + return; + } + System.arraycopy(inBytes, inOff, m_buf, m_bufPos, available); + inOff += available; + len -= available; + processBufferAAD(m_buf, 0); + //m_bufPos = 0; + } + while (len >= ASCON_AEAD_RATE) + { + processBufferAAD(inBytes, inOff); + inOff += ASCON_AEAD_RATE; + len -= ASCON_AEAD_RATE; + } + System.arraycopy(inBytes, inOff, m_buf, 0, len); + m_bufPos = len; + } + + public int processByte(byte in, byte[] out, int outOff) + throws DataLengthException + { + return processBytes(new byte[]{in}, 0, 1, out, outOff); + } + + public int processBytes(byte[] inBytes, int inOff, int len, byte[] outBytes, int outOff) + throws DataLengthException + { + if ((inOff + len) > inBytes.length) + { + throw new DataLengthException("input buffer too short"); + } + boolean forEncryption = checkData(); + int resultLength = 0; + + if (forEncryption) + { + if (m_bufPos > 0) + { + int available = ASCON_AEAD_RATE - m_bufPos; + if (len < available) + { + System.arraycopy(inBytes, inOff, m_buf, m_bufPos, len); + m_bufPos += len; + return 0; + } + + System.arraycopy(inBytes, inOff, m_buf, m_bufPos, available); + inOff += available; + len -= available; + + processBufferEncrypt(m_buf, 0, outBytes, outOff); + resultLength = ASCON_AEAD_RATE; + //m_bufPos = 0; + } + + while (len >= ASCON_AEAD_RATE) + { + processBufferEncrypt(inBytes, inOff, outBytes, outOff + resultLength); + inOff += ASCON_AEAD_RATE; + len -= ASCON_AEAD_RATE; + resultLength += ASCON_AEAD_RATE; + } + } + else + { + int available = m_bufferSizeDecrypt - m_bufPos; + if (len < available) + { + System.arraycopy(inBytes, inOff, m_buf, m_bufPos, len); + m_bufPos += len; + return 0; + } + + // NOTE: Need 'while' here because ASCON_AEAD_RATE < CRYPTO_ABYTES in some parameter sets + while (m_bufPos >= ASCON_AEAD_RATE) + { + processBufferDecrypt(m_buf, 0, outBytes, outOff + resultLength); + m_bufPos -= ASCON_AEAD_RATE; + System.arraycopy(m_buf, ASCON_AEAD_RATE, m_buf, 0, m_bufPos); + resultLength += ASCON_AEAD_RATE; + + available += ASCON_AEAD_RATE; + if (len < available) + { + System.arraycopy(inBytes, inOff, m_buf, m_bufPos, len); + m_bufPos += len; + return resultLength; + } + } + + available = ASCON_AEAD_RATE - m_bufPos; + System.arraycopy(inBytes, inOff, m_buf, m_bufPos, available); + inOff += available; + len -= available; + processBufferDecrypt(m_buf, 0, outBytes, outOff + resultLength); + resultLength += ASCON_AEAD_RATE; + //m_bufPos = 0; + + while (len >= m_bufferSizeDecrypt) + { + processBufferDecrypt(inBytes, inOff, outBytes, outOff + resultLength); + inOff += ASCON_AEAD_RATE; + len -= ASCON_AEAD_RATE; + resultLength += ASCON_AEAD_RATE; + } + } + + System.arraycopy(inBytes, inOff, m_buf, 0, len); + m_bufPos = len; + + return resultLength; + } + + public int doFinal(byte[] outBytes, int outOff) + throws IllegalStateException, InvalidCipherTextException, DataLengthException + { + boolean forEncryption = checkData(); + int resultLength; + if (forEncryption) + { + resultLength = m_bufPos + CRYPTO_ABYTES; + if (outOff + resultLength > outBytes.length) + { + throw new OutputLengthException("output buffer too short"); + } + processFinalEncrypt(m_buf, m_bufPos, outBytes, outOff); + mac = new byte[CRYPTO_ABYTES]; + setBytes(x3, mac, 0); + setBytes(x4, mac, 8); + System.arraycopy(mac, 0, outBytes, outOff + m_bufPos, CRYPTO_ABYTES); + reset(false); + } + else + { + if (m_bufPos < CRYPTO_ABYTES) + { + throw new InvalidCipherTextException("data too short"); + } + m_bufPos -= CRYPTO_ABYTES; + resultLength = m_bufPos; + if (outOff + resultLength > outBytes.length) + { + throw new OutputLengthException("output buffer too short"); + } + processFinalDecrypt(m_buf, m_bufPos, outBytes, outOff); + x3 ^= loadBytes(m_buf, m_bufPos); + x4 ^= loadBytes(m_buf, m_bufPos + 8); + if ((x3 | x4) != 0L) + { + throw new InvalidCipherTextException("mac check in " + getAlgorithmName() + " failed"); + } + reset(true); + } + return resultLength; + } + + public byte[] getMac() + { + return mac; + } + + public int getUpdateOutputSize(int len) + { + int total = Math.max(0, len); + switch (m_state.ord) + { + case DECINIT: + case DECAAD: + total = Math.max(0, total - CRYPTO_ABYTES); + break; + case DECDATA: + case DECFINAL: + total = Math.max(0, total + m_bufPos - CRYPTO_ABYTES); + break; + case ENCDATA: + case ENCFINAL: + total += m_bufPos; + break; + default: + break; + } + return total - total % ASCON_AEAD_RATE; + } + + public int getOutputSize(int len) + { + int total = Math.max(0, len); + + switch (m_state.ord) + { + case DECINIT: + case DECAAD: + return Math.max(0, total - CRYPTO_ABYTES); + case DECDATA: + case DECFINAL: + return Math.max(0, total + m_bufPos - CRYPTO_ABYTES); + case ENCDATA: + case ENCFINAL: + return total + m_bufPos + CRYPTO_ABYTES; + default: + return total + CRYPTO_ABYTES; + } + } + + public void reset() + { + reset(true); + } + + protected void reset(boolean clearMac) + { + if (clearMac) + { + mac = null; + } + Arrays.clear(m_buf); + m_bufPos = 0; + + switch (m_state.ord) + { + case DECINIT: + case ENCINIT: + break; + case DECAAD: + case DECDATA: + case DECFINAL: + m_state = DecInit; + break; + case ENCAAD: + case ENCDATA: + case ENCFINAL: + m_state = EncFinal; + return; + default: + throw new IllegalStateException(getAlgorithmName() + " needs to be initialized"); + } + ascon_aeadinit(); + if (initialAssociatedText != null) + { + processAADBytes(initialAssociatedText, 0, initialAssociatedText.length); + } + } + + public int getKeyBytesSize() + { + return CRYPTO_KEYBYTES; + } + + public int getIVBytesSize() + { + return CRYPTO_ABYTES; + } + + + public String getAlgorithmName() + { + return algorithmName; + } + + public abstract String getAlgorithmVersion(); + +} diff --git a/core/src/main/jdk1.4/org/bouncycastle/crypto/threshold/Polynomial.java b/core/src/main/jdk1.4/org/bouncycastle/crypto/threshold/Polynomial.java new file mode 100644 index 0000000000..8d1c78a36d --- /dev/null +++ b/core/src/main/jdk1.4/org/bouncycastle/crypto/threshold/Polynomial.java @@ -0,0 +1,287 @@ +package org.bouncycastle.crypto.threshold; + +abstract class Polynomial +{ + public static Polynomial newInstance(ShamirSecretSplitter.Algorithm algorithm, ShamirSecretSplitter.Mode mode) + { + if (mode == ShamirSecretSplitter.Mode.Native) + { + return new PolynomialNative(algorithm); + } + else + { + return new PolynomialTable(algorithm); + } + } + + protected abstract byte gfMul(int x, int y); + + protected abstract byte gfDiv(int x, int y); + + protected byte gfPow(int n, byte k) + { + int result = 1; + for (int i = 0; i < 8; i++) + { + if ((k & (1 << i)) != 0) + { + result = gfMul(result & 0xff, n & 0xff); + } + n = gfMul(n & 0xff, n & 0xff); + } + return (byte)result; + } + + public byte[] gfVecMul(byte[] xs, byte[][] yss) + { + byte[] result = new byte[yss[0].length]; + int sum; + for (int j = 0; j < yss[0].length; j++) + { + sum = 0; + for (int k = 0; k < xs.length; k++) + { + sum ^= gfMul(xs[k] & 0xff, yss[k][j] & 0xff); + } + result[j] = (byte)sum; + } + return result; + } +} + +class PolynomialTable + extends Polynomial +{ + private final byte[] LOG; + private final byte[] EXP; + private static final byte[] AES_LOG = { + (byte)0x00, (byte)0xff, (byte)0x19, (byte)0x01, (byte)0x32, (byte)0x02, (byte)0x1a, (byte)0xc6, + (byte)0x4b, (byte)0xc7, (byte)0x1b, (byte)0x68, (byte)0x33, (byte)0xee, (byte)0xdf, (byte)0x03, + (byte)0x64, (byte)0x04, (byte)0xe0, (byte)0x0e, (byte)0x34, (byte)0x8d, (byte)0x81, (byte)0xef, + (byte)0x4c, (byte)0x71, (byte)0x08, (byte)0xc8, (byte)0xf8, (byte)0x69, (byte)0x1c, (byte)0xc1, + (byte)0x7d, (byte)0xc2, (byte)0x1d, (byte)0xb5, (byte)0xf9, (byte)0xb9, (byte)0x27, (byte)0x6a, + (byte)0x4d, (byte)0xe4, (byte)0xa6, (byte)0x72, (byte)0x9a, (byte)0xc9, (byte)0x09, (byte)0x78, + (byte)0x65, (byte)0x2f, (byte)0x8a, (byte)0x05, (byte)0x21, (byte)0x0f, (byte)0xe1, (byte)0x24, + (byte)0x12, (byte)0xf0, (byte)0x82, (byte)0x45, (byte)0x35, (byte)0x93, (byte)0xda, (byte)0x8e, + (byte)0x96, (byte)0x8f, (byte)0xdb, (byte)0xbd, (byte)0x36, (byte)0xd0, (byte)0xce, (byte)0x94, + (byte)0x13, (byte)0x5c, (byte)0xd2, (byte)0xf1, (byte)0x40, (byte)0x46, (byte)0x83, (byte)0x38, + (byte)0x66, (byte)0xdd, (byte)0xfd, (byte)0x30, (byte)0xbf, (byte)0x06, (byte)0x8b, (byte)0x62, + (byte)0xb3, (byte)0x25, (byte)0xe2, (byte)0x98, (byte)0x22, (byte)0x88, (byte)0x91, (byte)0x10, + (byte)0x7e, (byte)0x6e, (byte)0x48, (byte)0xc3, (byte)0xa3, (byte)0xb6, (byte)0x1e, (byte)0x42, + (byte)0x3a, (byte)0x6b, (byte)0x28, (byte)0x54, (byte)0xfa, (byte)0x85, (byte)0x3d, (byte)0xba, + (byte)0x2b, (byte)0x79, (byte)0x0a, (byte)0x15, (byte)0x9b, (byte)0x9f, (byte)0x5e, (byte)0xca, + (byte)0x4e, (byte)0xd4, (byte)0xac, (byte)0xe5, (byte)0xf3, (byte)0x73, (byte)0xa7, (byte)0x57, + (byte)0xaf, (byte)0x58, (byte)0xa8, (byte)0x50, (byte)0xf4, (byte)0xea, (byte)0xd6, (byte)0x74, + (byte)0x4f, (byte)0xae, (byte)0xe9, (byte)0xd5, (byte)0xe7, (byte)0xe6, (byte)0xad, (byte)0xe8, + (byte)0x2c, (byte)0xd7, (byte)0x75, (byte)0x7a, (byte)0xeb, (byte)0x16, (byte)0x0b, (byte)0xf5, + (byte)0x59, (byte)0xcb, (byte)0x5f, (byte)0xb0, (byte)0x9c, (byte)0xa9, (byte)0x51, (byte)0xa0, + (byte)0x7f, (byte)0x0c, (byte)0xf6, (byte)0x6f, (byte)0x17, (byte)0xc4, (byte)0x49, (byte)0xec, + (byte)0xd8, (byte)0x43, (byte)0x1f, (byte)0x2d, (byte)0xa4, (byte)0x76, (byte)0x7b, (byte)0xb7, + (byte)0xcc, (byte)0xbb, (byte)0x3e, (byte)0x5a, (byte)0xfb, (byte)0x60, (byte)0xb1, (byte)0x86, + (byte)0x3b, (byte)0x52, (byte)0xa1, (byte)0x6c, (byte)0xaa, (byte)0x55, (byte)0x29, (byte)0x9d, + (byte)0x97, (byte)0xb2, (byte)0x87, (byte)0x90, (byte)0x61, (byte)0xbe, (byte)0xdc, (byte)0xfc, + (byte)0xbc, (byte)0x95, (byte)0xcf, (byte)0xcd, (byte)0x37, (byte)0x3f, (byte)0x5b, (byte)0xd1, + (byte)0x53, (byte)0x39, (byte)0x84, (byte)0x3c, (byte)0x41, (byte)0xa2, (byte)0x6d, (byte)0x47, + (byte)0x14, (byte)0x2a, (byte)0x9e, (byte)0x5d, (byte)0x56, (byte)0xf2, (byte)0xd3, (byte)0xab, + (byte)0x44, (byte)0x11, (byte)0x92, (byte)0xd9, (byte)0x23, (byte)0x20, (byte)0x2e, (byte)0x89, + (byte)0xb4, (byte)0x7c, (byte)0xb8, (byte)0x26, (byte)0x77, (byte)0x99, (byte)0xe3, (byte)0xa5, + (byte)0x67, (byte)0x4a, (byte)0xed, (byte)0xde, (byte)0xc5, (byte)0x31, (byte)0xfe, (byte)0x18, + (byte)0x0d, (byte)0x63, (byte)0x8c, (byte)0x80, (byte)0xc0, (byte)0xf7, (byte)0x70, (byte)0x07 + }; + /* given a j, (byte)return alpha^j, (byte)where alpha = mimimum primitive element (x + 1 = 3) */ + private static final byte[] AES_EXP = { + (byte)0x01, (byte)0x03, (byte)0x05, (byte)0x0f, (byte)0x11, (byte)0x33, (byte)0x55, (byte)0xff, + (byte)0x1a, (byte)0x2e, (byte)0x72, (byte)0x96, (byte)0xa1, (byte)0xf8, (byte)0x13, (byte)0x35, + (byte)0x5f, (byte)0xe1, (byte)0x38, (byte)0x48, (byte)0xd8, (byte)0x73, (byte)0x95, (byte)0xa4, + (byte)0xf7, (byte)0x02, (byte)0x06, (byte)0x0a, (byte)0x1e, (byte)0x22, (byte)0x66, (byte)0xaa, + (byte)0xe5, (byte)0x34, (byte)0x5c, (byte)0xe4, (byte)0x37, (byte)0x59, (byte)0xeb, (byte)0x26, + (byte)0x6a, (byte)0xbe, (byte)0xd9, (byte)0x70, (byte)0x90, (byte)0xab, (byte)0xe6, (byte)0x31, + (byte)0x53, (byte)0xf5, (byte)0x04, (byte)0x0c, (byte)0x14, (byte)0x3c, (byte)0x44, (byte)0xcc, + (byte)0x4f, (byte)0xd1, (byte)0x68, (byte)0xb8, (byte)0xd3, (byte)0x6e, (byte)0xb2, (byte)0xcd, + (byte)0x4c, (byte)0xd4, (byte)0x67, (byte)0xa9, (byte)0xe0, (byte)0x3b, (byte)0x4d, (byte)0xd7, + (byte)0x62, (byte)0xa6, (byte)0xf1, (byte)0x08, (byte)0x18, (byte)0x28, (byte)0x78, (byte)0x88, + (byte)0x83, (byte)0x9e, (byte)0xb9, (byte)0xd0, (byte)0x6b, (byte)0xbd, (byte)0xdc, (byte)0x7f, + (byte)0x81, (byte)0x98, (byte)0xb3, (byte)0xce, (byte)0x49, (byte)0xdb, (byte)0x76, (byte)0x9a, + (byte)0xb5, (byte)0xc4, (byte)0x57, (byte)0xf9, (byte)0x10, (byte)0x30, (byte)0x50, (byte)0xf0, + (byte)0x0b, (byte)0x1d, (byte)0x27, (byte)0x69, (byte)0xbb, (byte)0xd6, (byte)0x61, (byte)0xa3, + (byte)0xfe, (byte)0x19, (byte)0x2b, (byte)0x7d, (byte)0x87, (byte)0x92, (byte)0xad, (byte)0xec, + (byte)0x2f, (byte)0x71, (byte)0x93, (byte)0xae, (byte)0xe9, (byte)0x20, (byte)0x60, (byte)0xa0, + (byte)0xfb, (byte)0x16, (byte)0x3a, (byte)0x4e, (byte)0xd2, (byte)0x6d, (byte)0xb7, (byte)0xc2, + (byte)0x5d, (byte)0xe7, (byte)0x32, (byte)0x56, (byte)0xfa, (byte)0x15, (byte)0x3f, (byte)0x41, + (byte)0xc3, (byte)0x5e, (byte)0xe2, (byte)0x3d, (byte)0x47, (byte)0xc9, (byte)0x40, (byte)0xc0, + (byte)0x5b, (byte)0xed, (byte)0x2c, (byte)0x74, (byte)0x9c, (byte)0xbf, (byte)0xda, (byte)0x75, + (byte)0x9f, (byte)0xba, (byte)0xd5, (byte)0x64, (byte)0xac, (byte)0xef, (byte)0x2a, (byte)0x7e, + (byte)0x82, (byte)0x9d, (byte)0xbc, (byte)0xdf, (byte)0x7a, (byte)0x8e, (byte)0x89, (byte)0x80, + (byte)0x9b, (byte)0xb6, (byte)0xc1, (byte)0x58, (byte)0xe8, (byte)0x23, (byte)0x65, (byte)0xaf, + (byte)0xea, (byte)0x25, (byte)0x6f, (byte)0xb1, (byte)0xc8, (byte)0x43, (byte)0xc5, (byte)0x54, + (byte)0xfc, (byte)0x1f, (byte)0x21, (byte)0x63, (byte)0xa5, (byte)0xf4, (byte)0x07, (byte)0x09, + (byte)0x1b, (byte)0x2d, (byte)0x77, (byte)0x99, (byte)0xb0, (byte)0xcb, (byte)0x46, (byte)0xca, + (byte)0x45, (byte)0xcf, (byte)0x4a, (byte)0xde, (byte)0x79, (byte)0x8b, (byte)0x86, (byte)0x91, + (byte)0xa8, (byte)0xe3, (byte)0x3e, (byte)0x42, (byte)0xc6, (byte)0x51, (byte)0xf3, (byte)0x0e, + (byte)0x12, (byte)0x36, (byte)0x5a, (byte)0xee, (byte)0x29, (byte)0x7b, (byte)0x8d, (byte)0x8c, + (byte)0x8f, (byte)0x8a, (byte)0x85, (byte)0x94, (byte)0xa7, (byte)0xf2, (byte)0x0d, (byte)0x17, + (byte)0x39, (byte)0x4b, (byte)0xdd, (byte)0x7c, (byte)0x84, (byte)0x97, (byte)0xa2, (byte)0xfd, + (byte)0x1c, (byte)0x24, (byte)0x6c, (byte)0xb4, (byte)0xc7, (byte)0x52, (byte)0xf6, (byte)0x01 + }; + + /* given an alpha^j, (byte)where alpha = mimimum primitive element (x + 1 = 3), (byte)return j */ + private static final byte[] RSA_LOG = { + (byte)0xff, (byte)0x00, (byte)0x01, (byte)0x19, (byte)0x02, (byte)0x32, (byte)0x1a, (byte)0xc6, + (byte)0x03, (byte)0xdf, (byte)0x33, (byte)0xee, (byte)0x1b, (byte)0x68, (byte)0xc7, (byte)0x4b, + (byte)0x04, (byte)0x64, (byte)0xe0, (byte)0x0e, (byte)0x34, (byte)0x8d, (byte)0xef, (byte)0x81, + (byte)0x1c, (byte)0xc1, (byte)0x69, (byte)0xf8, (byte)0xc8, (byte)0x08, (byte)0x4c, (byte)0x71, + (byte)0x05, (byte)0x8a, (byte)0x65, (byte)0x2f, (byte)0xe1, (byte)0x24, (byte)0x0f, (byte)0x21, + (byte)0x35, (byte)0x93, (byte)0x8e, (byte)0xda, (byte)0xf0, (byte)0x12, (byte)0x82, (byte)0x45, + (byte)0x1d, (byte)0xb5, (byte)0xc2, (byte)0x7d, (byte)0x6a, (byte)0x27, (byte)0xf9, (byte)0xb9, + (byte)0xc9, (byte)0x9a, (byte)0x09, (byte)0x78, (byte)0x4d, (byte)0xe4, (byte)0x72, (byte)0xa6, + (byte)0x06, (byte)0xbf, (byte)0x8b, (byte)0x62, (byte)0x66, (byte)0xdd, (byte)0x30, (byte)0xfd, + (byte)0xe2, (byte)0x98, (byte)0x25, (byte)0xb3, (byte)0x10, (byte)0x91, (byte)0x22, (byte)0x88, + (byte)0x36, (byte)0xd0, (byte)0x94, (byte)0xce, (byte)0x8f, (byte)0x96, (byte)0xdb, (byte)0xbd, + (byte)0xf1, (byte)0xd2, (byte)0x13, (byte)0x5c, (byte)0x83, (byte)0x38, (byte)0x46, (byte)0x40, + (byte)0x1e, (byte)0x42, (byte)0xb6, (byte)0xa3, (byte)0xc3, (byte)0x48, (byte)0x7e, (byte)0x6e, + (byte)0x6b, (byte)0x3a, (byte)0x28, (byte)0x54, (byte)0xfa, (byte)0x85, (byte)0xba, (byte)0x3d, + (byte)0xca, (byte)0x5e, (byte)0x9b, (byte)0x9f, (byte)0x0a, (byte)0x15, (byte)0x79, (byte)0x2b, + (byte)0x4e, (byte)0xd4, (byte)0xe5, (byte)0xac, (byte)0x73, (byte)0xf3, (byte)0xa7, (byte)0x57, + (byte)0x07, (byte)0x70, (byte)0xc0, (byte)0xf7, (byte)0x8c, (byte)0x80, (byte)0x63, (byte)0x0d, + (byte)0x67, (byte)0x4a, (byte)0xde, (byte)0xed, (byte)0x31, (byte)0xc5, (byte)0xfe, (byte)0x18, + (byte)0xe3, (byte)0xa5, (byte)0x99, (byte)0x77, (byte)0x26, (byte)0xb8, (byte)0xb4, (byte)0x7c, + (byte)0x11, (byte)0x44, (byte)0x92, (byte)0xd9, (byte)0x23, (byte)0x20, (byte)0x89, (byte)0x2e, + (byte)0x37, (byte)0x3f, (byte)0xd1, (byte)0x5b, (byte)0x95, (byte)0xbc, (byte)0xcf, (byte)0xcd, + (byte)0x90, (byte)0x87, (byte)0x97, (byte)0xb2, (byte)0xdc, (byte)0xfc, (byte)0xbe, (byte)0x61, + (byte)0xf2, (byte)0x56, (byte)0xd3, (byte)0xab, (byte)0x14, (byte)0x2a, (byte)0x5d, (byte)0x9e, + (byte)0x84, (byte)0x3c, (byte)0x39, (byte)0x53, (byte)0x47, (byte)0x6d, (byte)0x41, (byte)0xa2, + (byte)0x1f, (byte)0x2d, (byte)0x43, (byte)0xd8, (byte)0xb7, (byte)0x7b, (byte)0xa4, (byte)0x76, + (byte)0xc4, (byte)0x17, (byte)0x49, (byte)0xec, (byte)0x7f, (byte)0x0c, (byte)0x6f, (byte)0xf6, + (byte)0x6c, (byte)0xa1, (byte)0x3b, (byte)0x52, (byte)0x29, (byte)0x9d, (byte)0x55, (byte)0xaa, + (byte)0xfb, (byte)0x60, (byte)0x86, (byte)0xb1, (byte)0xbb, (byte)0xcc, (byte)0x3e, (byte)0x5a, + (byte)0xcb, (byte)0x59, (byte)0x5f, (byte)0xb0, (byte)0x9c, (byte)0xa9, (byte)0xa0, (byte)0x51, + (byte)0x0b, (byte)0xf5, (byte)0x16, (byte)0xeb, (byte)0x7a, (byte)0x75, (byte)0x2c, (byte)0xd7, + (byte)0x4f, (byte)0xae, (byte)0xd5, (byte)0xe9, (byte)0xe6, (byte)0xe7, (byte)0xad, (byte)0xe8, + (byte)0x74, (byte)0xd6, (byte)0xf4, (byte)0xea, (byte)0xa8, (byte)0x50, (byte)0x58, (byte)0xaf + }; + /* given a j, (byte)return alpha^j, (byte)where alpha = mimimum primitive element (x + 1 = 3) */ + private static final byte[] RSA_EXP = { + (byte)0x01, (byte)0x02, (byte)0x04, (byte)0x08, (byte)0x10, (byte)0x20, (byte)0x40, (byte)0x80, + (byte)0x1d, (byte)0x3a, (byte)0x74, (byte)0xe8, (byte)0xcd, (byte)0x87, (byte)0x13, (byte)0x26, + (byte)0x4c, (byte)0x98, (byte)0x2d, (byte)0x5a, (byte)0xb4, (byte)0x75, (byte)0xea, (byte)0xc9, + (byte)0x8f, (byte)0x03, (byte)0x06, (byte)0x0c, (byte)0x18, (byte)0x30, (byte)0x60, (byte)0xc0, + (byte)0x9d, (byte)0x27, (byte)0x4e, (byte)0x9c, (byte)0x25, (byte)0x4a, (byte)0x94, (byte)0x35, + (byte)0x6a, (byte)0xd4, (byte)0xb5, (byte)0x77, (byte)0xee, (byte)0xc1, (byte)0x9f, (byte)0x23, + (byte)0x46, (byte)0x8c, (byte)0x05, (byte)0x0a, (byte)0x14, (byte)0x28, (byte)0x50, (byte)0xa0, + (byte)0x5d, (byte)0xba, (byte)0x69, (byte)0xd2, (byte)0xb9, (byte)0x6f, (byte)0xde, (byte)0xa1, + (byte)0x5f, (byte)0xbe, (byte)0x61, (byte)0xc2, (byte)0x99, (byte)0x2f, (byte)0x5e, (byte)0xbc, + (byte)0x65, (byte)0xca, (byte)0x89, (byte)0x0f, (byte)0x1e, (byte)0x3c, (byte)0x78, (byte)0xf0, + (byte)0xfd, (byte)0xe7, (byte)0xd3, (byte)0xbb, (byte)0x6b, (byte)0xd6, (byte)0xb1, (byte)0x7f, + (byte)0xfe, (byte)0xe1, (byte)0xdf, (byte)0xa3, (byte)0x5b, (byte)0xb6, (byte)0x71, (byte)0xe2, + (byte)0xd9, (byte)0xaf, (byte)0x43, (byte)0x86, (byte)0x11, (byte)0x22, (byte)0x44, (byte)0x88, + (byte)0x0d, (byte)0x1a, (byte)0x34, (byte)0x68, (byte)0xd0, (byte)0xbd, (byte)0x67, (byte)0xce, + (byte)0x81, (byte)0x1f, (byte)0x3e, (byte)0x7c, (byte)0xf8, (byte)0xed, (byte)0xc7, (byte)0x93, + (byte)0x3b, (byte)0x76, (byte)0xec, (byte)0xc5, (byte)0x97, (byte)0x33, (byte)0x66, (byte)0xcc, + (byte)0x85, (byte)0x17, (byte)0x2e, (byte)0x5c, (byte)0xb8, (byte)0x6d, (byte)0xda, (byte)0xa9, + (byte)0x4f, (byte)0x9e, (byte)0x21, (byte)0x42, (byte)0x84, (byte)0x15, (byte)0x2a, (byte)0x54, + (byte)0xa8, (byte)0x4d, (byte)0x9a, (byte)0x29, (byte)0x52, (byte)0xa4, (byte)0x55, (byte)0xaa, + (byte)0x49, (byte)0x92, (byte)0x39, (byte)0x72, (byte)0xe4, (byte)0xd5, (byte)0xb7, (byte)0x73, + (byte)0xe6, (byte)0xd1, (byte)0xbf, (byte)0x63, (byte)0xc6, (byte)0x91, (byte)0x3f, (byte)0x7e, + (byte)0xfc, (byte)0xe5, (byte)0xd7, (byte)0xb3, (byte)0x7b, (byte)0xf6, (byte)0xf1, (byte)0xff, + (byte)0xe3, (byte)0xdb, (byte)0xab, (byte)0x4b, (byte)0x96, (byte)0x31, (byte)0x62, (byte)0xc4, + (byte)0x95, (byte)0x37, (byte)0x6e, (byte)0xdc, (byte)0xa5, (byte)0x57, (byte)0xae, (byte)0x41, + (byte)0x82, (byte)0x19, (byte)0x32, (byte)0x64, (byte)0xc8, (byte)0x8d, (byte)0x07, (byte)0x0e, + (byte)0x1c, (byte)0x38, (byte)0x70, (byte)0xe0, (byte)0xdd, (byte)0xa7, (byte)0x53, (byte)0xa6, + (byte)0x51, (byte)0xa2, (byte)0x59, (byte)0xb2, (byte)0x79, (byte)0xf2, (byte)0xf9, (byte)0xef, + (byte)0xc3, (byte)0x9b, (byte)0x2b, (byte)0x56, (byte)0xac, (byte)0x45, (byte)0x8a, (byte)0x09, + (byte)0x12, (byte)0x24, (byte)0x48, (byte)0x90, (byte)0x3d, (byte)0x7a, (byte)0xf4, (byte)0xf5, + (byte)0xf7, (byte)0xf3, (byte)0xfb, (byte)0xeb, (byte)0xcb, (byte)0x8b, (byte)0x0b, (byte)0x16, + (byte)0x2c, (byte)0x58, (byte)0xb0, (byte)0x7d, (byte)0xfa, (byte)0xe9, (byte)0xcf, (byte)0x83, + (byte)0x1b, (byte)0x36, (byte)0x6c, (byte)0xd8, (byte)0xad, (byte)0x47, (byte)0x8e, (byte)0x01 + }; + + public PolynomialTable(ShamirSecretSplitter.Algorithm algorithm) + { + switch (algorithm.ord) + { + case ShamirSecretSplitter._AES: + LOG = AES_LOG; + EXP = AES_EXP; + break; + case ShamirSecretSplitter._RSA: + LOG = RSA_LOG; + EXP = RSA_EXP; + break; + default: + throw new IllegalArgumentException("The algorithm is not correct"); + } + } + + protected byte gfMul(int x, int y) + { + if (x == 0 || y == 0) + { + return 0; + } + return (byte)(EXP[((LOG[x] & 0xff) + (LOG[y] & 0xff)) % 255] & 0xff); + } + + protected byte gfDiv(int x, int y) + { + if (x == 0) + { + return 0; + } + return EXP[((LOG[x] & 0xff) - (LOG[y] & 0xff) + 255) % 255]; + } +} + +class PolynomialNative + extends Polynomial +{ + private final int IRREDUCIBLE; + + public PolynomialNative(ShamirSecretSplitter.Algorithm algorithm) + { + switch (algorithm.ord) + { + case ShamirSecretSplitter._AES: + IRREDUCIBLE = 0x11B; + break; + case ShamirSecretSplitter._RSA: + IRREDUCIBLE = 0x11D; + break; + default: + throw new IllegalArgumentException("The algorithm is not correct"); + } + } + + protected byte gfMul(int x, int y) + { + //pmult + int result = 0; + while (y > 0) + { + if ((y & 1) != 0) + { // If the lowest bit of y is 1 + result ^= x; // XOR x into the result + } + x <<= 1; // Shift x left (multiply by 2 in GF) + if ((x & 0x100) != 0) + { // If x is larger than 8 bits, reduce + x ^= IRREDUCIBLE; // XOR with the irreducible polynomial + } + y >>= 1; // Shift y right + } + //mod + while (result >= (1 << 8)) + { + if ((result & (1 << 8)) != 0) + { + result ^= IRREDUCIBLE; + } + result <<= 1; + } + return (byte) (result & 0xFF); + } + + protected byte gfDiv(int x, int y) + { + return gfMul(x, gfPow((byte)y, (byte)254) & 0xff); + } +} diff --git a/core/src/main/jdk1.4/org/bouncycastle/crypto/threshold/ShamirSecretSplitter.java b/core/src/main/jdk1.4/org/bouncycastle/crypto/threshold/ShamirSecretSplitter.java new file mode 100644 index 0000000000..92607b5cd3 --- /dev/null +++ b/core/src/main/jdk1.4/org/bouncycastle/crypto/threshold/ShamirSecretSplitter.java @@ -0,0 +1,153 @@ +package org.bouncycastle.crypto.threshold; + +import java.io.IOException; +import java.security.SecureRandom; + +import org.bouncycastle.util.Arrays; + + +public class ShamirSecretSplitter + implements SecretSplitter +{ + static final int _AES = 0; + static final int _RSA = 1; + + public static class Algorithm + { + public static final Algorithm AES = new Algorithm(_AES); + public static final Algorithm RSA = new Algorithm(_RSA); + + int ord; + + private Algorithm(int ord) + { + this.ord = ord; + } + } + + static final int _Native = 0; + static final int _Table = 1; + + public static class Mode + { + public static final Mode Native = new Mode(_Native); + public static final Mode Table = new Mode(_Table); + + int ord; + + private Mode(int ord) + { + this.ord = ord; + } + } + + private final Polynomial poly; + /** + * Length of the secret + */ + protected int l; + + protected SecureRandom random; + + public ShamirSecretSplitter(Algorithm algorithm, Mode mode, int l, SecureRandom random) + { + if (l < 0 || l > 65534) + { + throw new IllegalArgumentException("Invalid input: l ranges from 0 to 65534 (2^16-2) bytes."); + } + + poly = Polynomial.newInstance(algorithm, mode); + this.l = l; + this.random = random; + } + + + public SplitSecret split(int m, int n) + { + byte[][] p = initP(m, n); + byte[][] sr = new byte[m][l]; + ShamirSplitSecretShare[] secretShares = new ShamirSplitSecretShare[l]; + int i; + for (i = 0; i < m; i++) + { + random.nextBytes(sr[i]); + } + for (i = 0; i < p.length; i++) + { + secretShares[i] = new ShamirSplitSecretShare(poly.gfVecMul(p[i], sr), i + 1); + } + return new ShamirSplitSecret(poly, secretShares); + } + + @Override + public SplitSecret splitAround(SecretShare s, int m, int n) + throws IOException + { + byte[][] p = initP(m, n); + byte[][] sr = new byte[m][l]; + ShamirSplitSecretShare[] secretShares = new ShamirSplitSecretShare[l]; + byte[] ss0 = s.getEncoded(); + secretShares[0] = new ShamirSplitSecretShare(ss0, 1); + int i, j; + byte tmp; + for (i = 0; i < m; i++) + { + random.nextBytes(sr[i]); + } + for (i = 0; i < l; i++) + { + tmp = sr[1][i]; + for (j = 2; j < m; j++) + { + tmp ^= sr[j][i]; + } + sr[0][i] = (byte)(tmp ^ ss0[i]); + } + for (i = 1; i < p.length; i++) + { + secretShares[i] = new ShamirSplitSecretShare(poly.gfVecMul(p[i], sr), i + 1); + } + + return new ShamirSplitSecret(poly, secretShares); + } + + @Override + public SplitSecret resplit(byte[] secret, int m, int n) + { + byte[][] p = initP(m, n); + byte[][] sr = new byte[m][l]; + ShamirSplitSecretShare[] secretShares = new ShamirSplitSecretShare[l]; + sr[0] = Arrays.clone(secret); + int i; + for (i = 1; i < m; i++) + { + random.nextBytes(sr[i]); + } + for (i = 0; i < p.length; i++) + { + secretShares[i] = new ShamirSplitSecretShare(poly.gfVecMul(p[i], sr), i + 1); + } + return new ShamirSplitSecret(poly, secretShares); + } + + private byte[][] initP(int m, int n) + { + if (m < 1 || m > 255) + { + throw new IllegalArgumentException("Invalid input: m must be less than 256 and positive."); + } + if (n < m || n > 255) + { + throw new IllegalArgumentException("Invalid input: n must be less than 256 and greater than or equal to n."); + } + byte[][] p = new byte[n][m]; + for (int i = 0; i < n; i++) + { + for (int j = 0; j < m; j++) + { + p[i][j] = poly.gfPow((byte)(i + 1), (byte)j); + } + } + return p; + } +} diff --git a/core/src/main/jdk1.4/org/bouncycastle/crypto/threshold/ShamirSplitSecret.java b/core/src/main/jdk1.4/org/bouncycastle/crypto/threshold/ShamirSplitSecret.java new file mode 100644 index 0000000000..d148cdd1e8 --- /dev/null +++ b/core/src/main/jdk1.4/org/bouncycastle/crypto/threshold/ShamirSplitSecret.java @@ -0,0 +1,91 @@ +package org.bouncycastle.crypto.threshold; + +import java.io.IOException; + +public class ShamirSplitSecret + implements SplitSecret +{ + private final ShamirSplitSecretShare[] secretShares; + private final Polynomial poly; + + public ShamirSplitSecret(ShamirSecretSplitter.Algorithm algorithm, ShamirSecretSplitter.Mode mode, ShamirSplitSecretShare[] secretShares) + { + this.secretShares = secretShares; + this.poly = Polynomial.newInstance(algorithm, mode); + } + + ShamirSplitSecret(Polynomial poly, ShamirSplitSecretShare[] secretShares) + { + this.secretShares = secretShares; + this.poly = poly; + } + + public SecretShare[] getSecretShares() + { + return secretShares; + } + + public ShamirSplitSecret multiple(int mul) + throws IOException + { + byte[] ss; + for (int i = 0; i < secretShares.length; ++i) + { + ss = secretShares[i].getEncoded(); + for (int j = 0; j < ss.length; ++j) + { + ss[j] = poly.gfMul(ss[j] & 0xFF, mul); + } + secretShares[i] = new ShamirSplitSecretShare(ss, i + 1); + } + return this; + } + + public ShamirSplitSecret divide(int div) + throws IOException + { + byte[] ss; + for (int i = 0; i < secretShares.length; ++i) + { + ss = secretShares[i].getEncoded(); + for (int j = 0; j < ss.length; ++j) + { + ss[j] = poly.gfDiv(ss[j] & 0xFF, div); + } + secretShares[i] = new ShamirSplitSecretShare(ss, i + 1); + } + return this; + } + + @Override + public byte[] getSecret() + throws IOException + { + int n = secretShares.length; + byte[] r = new byte[n]; + byte tmp; + byte[] products = new byte[n - 1]; + byte[][] splits = new byte[n][secretShares[0].getEncoded().length]; + for (int i = 0; i < n; i++) + { + splits[i] = secretShares[i].getEncoded(); + tmp = 0; + for (int j = 0; j < n; j++) + { + if (j != i) + { + products[tmp++] = poly.gfDiv(secretShares[j].r, secretShares[i].r ^ secretShares[j].r); + } + } + + tmp = 1; + for (int prdI = 0; prdI != products.length; prdI++) + { + tmp = poly.gfMul(tmp & 0xff, products[prdI] & 0xff); + } + r[i] = tmp; + } + + return poly.gfVecMul(r, splits); + } +} diff --git a/core/src/test/java/org/bouncycastle/asn1/test/ObjectIdentifierTest.java b/core/src/test/java/org/bouncycastle/asn1/test/ObjectIdentifierTest.java index 9e20e54856..36b032ee02 100644 --- a/core/src/test/java/org/bouncycastle/asn1/test/ObjectIdentifierTest.java +++ b/core/src/test/java/org/bouncycastle/asn1/test/ObjectIdentifierTest.java @@ -40,7 +40,7 @@ public void performTest() System.setProperty("org.bouncycastle.asn1.allow_wrong_oid_enc", "true"); String oid = ASN1ObjectIdentifier.getInstance(faultyOID).getId(); - System.clearProperty("org.bouncycastle.asn1.allow_wrong_oid_enc"); + System.setProperty("org.bouncycastle.asn1.allow_wrong_oid_enc", "false"); isEquals("1.2.840.114283.4.0", oid); // exercise the object cache diff --git a/core/src/test/java/org/bouncycastle/crypto/threshold/test/ShamirSecretSplitterTest.java b/core/src/test/java/org/bouncycastle/crypto/threshold/test/ShamirSecretSplitterTest.java index 50d4790027..cd81bda2a4 100644 --- a/core/src/test/java/org/bouncycastle/crypto/threshold/test/ShamirSecretSplitterTest.java +++ b/core/src/test/java/org/bouncycastle/crypto/threshold/test/ShamirSecretSplitterTest.java @@ -4,6 +4,7 @@ import java.security.SecureRandom; import junit.framework.TestCase; +import org.bouncycastle.crypto.threshold.SecretShare; import org.bouncycastle.crypto.threshold.ShamirSecretSplitter; import org.bouncycastle.crypto.threshold.ShamirSplitSecret; import org.bouncycastle.crypto.threshold.ShamirSplitSecretShare; @@ -40,16 +41,16 @@ public void testShamirSecretResplit() ShamirSecretSplitter.Mode mode = ShamirSecretSplitter.Mode.Table; ShamirSecretSplitter splitter = new ShamirSecretSplitter(algorithm, mode, l, random); - ShamirSplitSecret splitSecret = splitter.split(m, n); - ShamirSplitSecretShare[] secretShares = splitSecret.getSecretShares(); + ShamirSplitSecret splitSecret = (ShamirSplitSecret)splitter.split(m, n); + ShamirSplitSecretShare[] secretShares = (ShamirSplitSecretShare[])splitSecret.getSecretShares(); ShamirSplitSecretShare[] secretShares1 = new ShamirSplitSecretShare[]{secretShares[0], secretShares[1], secretShares[2]}; ShamirSplitSecret splitSecret1 = new ShamirSplitSecret(algorithm, mode, secretShares1); byte[] secret1 = splitSecret1.getSecret(); - ShamirSplitSecret splitSecret2 = splitter.resplit(secret1, m, n); - ShamirSplitSecretShare[] secretShares2 = splitSecret2.getSecretShares(); + ShamirSplitSecret splitSecret2 = (ShamirSplitSecret)splitter.resplit(secret1, m, n); + ShamirSplitSecretShare[] secretShares2 = (ShamirSplitSecretShare[])splitSecret2.getSecretShares(); ShamirSplitSecretShare[] secretShares3 = new ShamirSplitSecretShare[]{secretShares2[0], secretShares2[1], secretShares2[2]}; ShamirSplitSecret splitSecret3 = new ShamirSplitSecret(algorithm, mode, secretShares3); byte[] secret3 = splitSecret3.getSecret(); @@ -69,8 +70,8 @@ public void testShamirSecretMultipleDivide() ShamirSecretSplitter.Mode mode = ShamirSecretSplitter.Mode.Table; ShamirSecretSplitter splitter = new ShamirSecretSplitter(algorithm, mode, l, random); - ShamirSplitSecret splitSecret = splitter.split(m, n); - ShamirSplitSecretShare[] secretShares = splitSecret.getSecretShares(); + ShamirSplitSecret splitSecret = (ShamirSplitSecret)splitter.split(m, n); + ShamirSplitSecretShare[] secretShares = (ShamirSplitSecretShare[])splitSecret.getSecretShares(); ShamirSplitSecretShare[] secretShares1 = new ShamirSplitSecretShare[]{secretShares[0], secretShares[1], secretShares[2]}; ShamirSplitSecret splitSecret1 = new ShamirSplitSecret(algorithm, mode, secretShares1); @@ -78,13 +79,13 @@ public void testShamirSecretMultipleDivide() int mul = random.nextInt(255); splitSecret.multiple(mul); - secretShares = splitSecret.getSecretShares(); + secretShares = (ShamirSplitSecretShare[])splitSecret.getSecretShares(); ShamirSplitSecretShare[] secretShares4 = new ShamirSplitSecretShare[]{secretShares[1], secretShares[2], secretShares[5]}; ShamirSplitSecret splitSecret4 = new ShamirSplitSecret(algorithm, mode, secretShares4); byte[] secret4 = splitSecret4.getSecret(); splitSecret.divide(mul); - secretShares = splitSecret.getSecretShares(); + secretShares = (ShamirSplitSecretShare[])splitSecret.getSecretShares(); ShamirSplitSecretShare[] secretShares2 = new ShamirSplitSecretShare[]{secretShares[4], secretShares[7], secretShares[8]}; ShamirSplitSecret splitSecret2 = new ShamirSplitSecret(algorithm, mode, secretShares2); byte[] secret2 = splitSecret2.getSecret(); @@ -112,8 +113,8 @@ public void testShamirSecretSplitterSplitAround() //random.nextBytes(seed); //System.out.println(Hex.decode(seed)); ShamirSplitSecretShare ss = new ShamirSplitSecretShare(seed); - ShamirSplitSecret splitSecret = splitter.splitAround(ss, m, n); - ShamirSplitSecretShare[] secretShares = splitSecret.getSecretShares(); + ShamirSplitSecret splitSecret = (ShamirSplitSecret)splitter.splitAround(ss, m, n); + ShamirSplitSecretShare[] secretShares = (ShamirSplitSecretShare[])splitSecret.getSecretShares(); assertTrue(Arrays.areEqual(secretShares[0].getEncoded(), seed)); ShamirSplitSecretShare[] secretShares1 = new ShamirSplitSecretShare[]{secretShares[0], secretShares[1], secretShares[2]}; @@ -150,8 +151,8 @@ public void testShamirSecretSplitter() ShamirSecretSplitter.Algorithm algorithm = ShamirSecretSplitter.Algorithm.AES; ShamirSecretSplitter.Mode mode = ShamirSecretSplitter.Mode.Table; ShamirSecretSplitter splitter = new ShamirSecretSplitter(algorithm, mode, l, new SecureRandom());//, secretshare); - ShamirSplitSecret splitSecret = splitter.split(m, n); //integers multiply/ divide - ShamirSplitSecretShare[] secretShares = splitSecret.getSecretShares(); + ShamirSplitSecret splitSecret = (ShamirSplitSecret)splitter.split(m, n); //integers multiply/ divide + ShamirSplitSecretShare[] secretShares = (ShamirSplitSecretShare[])splitSecret.getSecretShares(); ShamirSplitSecretShare[] secretShares1 = new ShamirSplitSecretShare[]{secretShares[0], secretShares[1], secretShares[2]}; ShamirSplitSecret splitSecret1 = new ShamirSplitSecret(algorithm, mode, secretShares1); @@ -1069,8 +1070,9 @@ static SecureRandom getSecureRandom(byte[][] sr) byte[] source = new byte[sr.length * sr[0].length]; int currentIndex = 0; - for (byte[] subArray : sr) + for (int i = 0; i != sr.length; i++) { + byte[] subArray = sr[i]; System.arraycopy(subArray, 0, source, currentIndex, subArray.length); currentIndex += subArray.length; } @@ -1090,13 +1092,13 @@ static ShamirSplitSecretShare[] getShamirSplitSecretShareArray(int[] rr, byte[][ static void testMatrixMultiplication(ShamirSecretSplitter poly, byte[][] splits, int m, int n) throws IOException { - ShamirSplitSecretShare[] secretShares = poly.split(m, n).getSecretShares(); + SecretShare[] secretShares = poly.split(m, n).getSecretShares(); byte[][] result = new byte[splits.length][splits[0].length]; for (int i = 0; i < result.length; ++i) { result[i] = secretShares[i].getEncoded(); + assertTrue(Arrays.areEqual(splits[i], result[i])); } - assertEquals(java.util.Arrays.deepToString(splits), java.util.Arrays.deepToString(result)); } public void testRecombine(ShamirSplitSecret splitSecret, byte[] secret) diff --git a/pg/src/main/java/org/bouncycastle/bcpg/KeyIdentifier.java b/pg/src/main/java/org/bouncycastle/bcpg/KeyIdentifier.java index 080c54f0aa..16c58f15ef 100644 --- a/pg/src/main/java/org/bouncycastle/bcpg/KeyIdentifier.java +++ b/pg/src/main/java/org/bouncycastle/bcpg/KeyIdentifier.java @@ -164,8 +164,10 @@ public boolean matches(KeyIdentifier other) public static boolean matches(List identifiers, KeyIdentifier identifier, boolean explicit) { - for (KeyIdentifier candidate : identifiers) + for (Iterator it = identifiers.iterator(); it.hasNext();) { + KeyIdentifier candidate = (KeyIdentifier)it.next(); + if (!explicit && candidate.isWildcard()) { return true; diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataGenerator.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataGenerator.java index 4c7f23a603..a0e3d295ca 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataGenerator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPEncryptedDataGenerator.java @@ -218,7 +218,7 @@ else if (directS2K) BCPGHeaderObject encOut; for (int i = 0; i < methods.size(); i++) { - PGPKeyEncryptionMethodGenerator method = methods.get(i); + PGPKeyEncryptionMethodGenerator method = (PGPKeyEncryptionMethodGenerator)methods.get(i); pOut.writePacket(method.generate(dataEncryptorBuilder, sessionKey)); } try diff --git a/pg/src/main/java/org/bouncycastle/openpgp/PGPSignatureSubpacketGenerator.java b/pg/src/main/java/org/bouncycastle/openpgp/PGPSignatureSubpacketGenerator.java index 9acbba5128..4330035bc1 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/PGPSignatureSubpacketGenerator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/PGPSignatureSubpacketGenerator.java @@ -631,7 +631,7 @@ public boolean removePacketsOfType(int subpacketType) boolean remove = false; for (int i = packets.size() - 1; i >= 0; i--) { - if (packets.get(i).getType() == subpacketType) + if (((SignatureSubpacket)packets.get(i)).getType() == subpacketType) { packets.remove(i); remove = true; @@ -686,7 +686,7 @@ public SignatureSubpacket[] getSubpackets( public PGPSignatureSubpacketVector generate() { return new PGPSignatureSubpacketVector( - packets.toArray(new SignatureSubpacket[0])); + (SignatureSubpacket[])packets.toArray(new SignatureSubpacket[0])); } private boolean contains(int type) diff --git a/pg/src/main/java/org/bouncycastle/openpgp/api/OpenPGPV6KeyGenerator.java b/pg/src/main/java/org/bouncycastle/openpgp/api/OpenPGPV6KeyGenerator.java index 0a47d550a8..e512b3a3e8 100644 --- a/pg/src/main/java/org/bouncycastle/openpgp/api/OpenPGPV6KeyGenerator.java +++ b/pg/src/main/java/org/bouncycastle/openpgp/api/OpenPGPV6KeyGenerator.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Date; +import java.util.Iterator; import java.util.List; import org.bouncycastle.bcpg.AEADAlgorithmTags; @@ -680,7 +681,7 @@ public WithPrimaryKey addUserId( SignatureSubpacketsFunction userIdSubpackets) throws PGPException { - if (userId == null || userId.trim().isEmpty()) + if (userId == null || userId.trim().length() == 0) { throw new IllegalArgumentException("User-ID cannot be null or empty."); } @@ -1090,8 +1091,9 @@ public PGPSecretKeyRing build() List keys = new ArrayList(); keys.add(primarySecretKey); - for (Key key : subkeys) + for (Iterator it = subkeys.iterator(); it.hasNext();) { + Key key = (Key)it.next(); PGPSecretKey subkey = new PGPSecretKey( key.pair.getPrivateKey(), key.pair.getPublicKey(), @@ -1127,8 +1129,9 @@ public PGPSecretKeyRing build(char[] passphrase) List keys = new ArrayList(); keys.add(primarySecretKey); - for (Key key : subkeys) + for (Iterator it = subkeys.iterator(); it.hasNext();) { + Key key = (Key)it.next(); PBESecretKeyEncryptor subkeyEncryptor = impl.keyEncryptorBuilderProvider .build(passphrase, key.pair.getPublicKey().getPublicKeyPacket()); sanitizeKeyEncryptor(subkeyEncryptor); diff --git a/pg/src/test/java/org/bouncycastle/openpgp/api/test/OpenPGPV6KeyGeneratorTest.java b/pg/src/test/java/org/bouncycastle/openpgp/api/test/OpenPGPV6KeyGeneratorTest.java index afa01a257f..e69954ee6c 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/api/test/OpenPGPV6KeyGeneratorTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/api/test/OpenPGPV6KeyGeneratorTest.java @@ -98,9 +98,9 @@ private void testGenerateSignOnlyKeyBaseCase(APIProvider apiProvider) PGPSecretKeyRing secretKeys = generator.signOnlyKey(null); Iterator it = secretKeys.getSecretKeys(); - PGPSecretKey primaryKey = it.next(); + PGPSecretKey primaryKey = (PGPSecretKey)it.next(); isFalse("sign-only key MUST consists of only a single key", it.hasNext()); - PGPSignature directKeySignature = primaryKey.getPublicKey().getKeySignatures().next(); + PGPSignature directKeySignature = (PGPSignature)primaryKey.getPublicKey().getKeySignatures().next(); isNotNull("Key MUST have direct-key signature", directKeySignature); isEquals("Direct-key signature MUST be version 6", SignaturePacket.VERSION_6, directKeySignature.getVersion()); @@ -125,7 +125,7 @@ private void testGenerateAEADProtectedSignOnlyKey(APIProvider apiProvider) PGPSecretKeyRing secretKeys = generator.signOnlyKey("passphrase".toCharArray()); Iterator it = secretKeys.getSecretKeys(); - PGPSecretKey primaryKey = it.next(); + PGPSecretKey primaryKey = (PGPSecretKey)it.next(); isFalse("sign-only key MUST consists of only a single key", it.hasNext()); isEquals("Key MUST be AEAD-protected", SecretKeyPacket.USAGE_AEAD, primaryKey.getS2KUsage()); @@ -142,7 +142,7 @@ private void testGenerateCFBProtectedSignOnlyKey(APIProvider apiProvider) PGPSecretKeyRing secretKeys = generator.signOnlyKey("passphrase".toCharArray()); Iterator it = secretKeys.getSecretKeys(); - PGPSecretKey primaryKey = it.next(); + PGPSecretKey primaryKey = (PGPSecretKey)it.next(); isFalse("sign-only key MUST consists of only a single key", it.hasNext()); isEquals("Key MUST be CFB-protected", SecretKeyPacket.USAGE_SHA1, primaryKey.getS2KUsage()); @@ -161,13 +161,13 @@ private void testGenerateClassicKeyBaseCase(APIProvider apiProvider) .classicKey("Alice ", null); Iterator keys = secretKeys.getSecretKeys(); - PGPSecretKey primaryKey = keys.next(); + PGPSecretKey primaryKey = (PGPSecretKey)keys.next(); isEquals("Primary key version mismatch", PublicKeyPacket.VERSION_6, primaryKey.getPublicKey().getVersion()); isEquals(creationTime, primaryKey.getPublicKey().getCreationTime()); isTrue("Primary key uses signing-capable algorithm", PublicKeyUtils.isSigningAlgorithm(primaryKey.getPublicKey().getAlgorithm())); - PGPSignature directKeySig = primaryKey.getPublicKey().getKeySignatures().next(); + PGPSignature directKeySig = (PGPSignature)primaryKey.getPublicKey().getKeySignatures().next(); isEquals("Primary key of a classic key MUST carry C key flag.", KeyFlags.CERTIFY_OTHER, directKeySig.getHashedSubPackets().getKeyFlags()); @@ -177,26 +177,26 @@ private void testGenerateClassicKeyBaseCase(APIProvider apiProvider) isFalse(uids.hasNext()); // Test signing subkey - PGPSecretKey signingSubkey = keys.next(); + PGPSecretKey signingSubkey = (PGPSecretKey)keys.next(); isEquals("Signing key version mismatch", PublicKeyPacket.VERSION_6, signingSubkey.getPublicKey().getVersion()); isTrue("Signing subkey uses signing-capable algorithm", PublicKeyUtils.isSigningAlgorithm(signingSubkey.getPublicKey().getAlgorithm())); isEquals(creationTime, signingSubkey.getPublicKey().getCreationTime()); - PGPSignature signingKeyBinding = signingSubkey.getPublicKey().getKeySignatures().next(); + PGPSignature signingKeyBinding = (PGPSignature)signingSubkey.getPublicKey().getKeySignatures().next(); isEquals("Signing subkey MUST carry S key flag.", KeyFlags.SIGN_DATA, signingKeyBinding.getHashedSubPackets().getKeyFlags()); isNotNull("Signing subkey binding MUST carry primary key binding sig", signingKeyBinding.getHashedSubPackets().getEmbeddedSignatures().get(0)); // Test encryption subkey - PGPSecretKey encryptionSubkey = keys.next(); + PGPSecretKey encryptionSubkey = (PGPSecretKey)keys.next(); isEquals("Encryption key version mismatch", PublicKeyPacket.VERSION_6, encryptionSubkey.getPublicKey().getVersion()); isTrue("Encryption subkey uses encryption-capable algorithm", encryptionSubkey.getPublicKey().isEncryptionKey()); isEquals(creationTime, encryptionSubkey.getPublicKey().getCreationTime()); - PGPSignature encryptionKeyBinding = encryptionSubkey.getPublicKey().getKeySignatures().next(); + PGPSignature encryptionKeyBinding = (PGPSignature)encryptionSubkey.getPublicKey().getKeySignatures().next(); isEquals("Encryption key MUST carry encryption flags", KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, encryptionKeyBinding.getHashedSubPackets().getKeyFlags()); @@ -205,8 +205,9 @@ private void testGenerateClassicKeyBaseCase(APIProvider apiProvider) isFalse(keys.hasNext()); // Test all keys are unprotected - for (PGPSecretKey key : secretKeys) + for (Iterator it = secretKeys.getSecretKeys(); it.hasNext();) { + PGPSecretKey key = (PGPSecretKey)it.next(); isEquals("(Sub-)keys MUST be unprotected", SecretKeyPacket.USAGE_NONE, key.getS2KUsage()); } } @@ -220,12 +221,13 @@ private void testGenerateProtectedTypicalKey(APIProvider apiProvider) .classicKey("Alice ", "passphrase".toCharArray()); // Test creation time - for (PGPPublicKey key : secretKeys.toCertificate()) + for (Iterator it = secretKeys.toCertificate().iterator(); it.hasNext();) { + PGPPublicKey key = (PGPPublicKey)it.next(); isEquals(creationTime, key.getCreationTime()); - for (Iterator it = key.getSignatures(); it.hasNext(); ) + for (Iterator its = key.getSignatures(); its.hasNext(); ) { - PGPSignature sig = it.next(); + PGPSignature sig = (PGPSignature)its.next(); isEquals(creationTime, sig.getCreationTime()); } } @@ -236,8 +238,9 @@ private void testGenerateProtectedTypicalKey(APIProvider apiProvider) isEquals("Alice ", uids.next()); isFalse(uids.hasNext()); - for (PGPSecretKey key : secretKeys) + for (Iterator it = secretKeys.getSecretKeys(); it.hasNext();) { + PGPSecretKey key = (PGPSecretKey)it.next(); isEquals("(Sub-)keys MUST be protected", SecretKeyPacket.USAGE_AEAD, key.getS2KUsage()); } } @@ -252,14 +255,14 @@ private void testGenerateEd25519x25519Key(APIProvider apiProvider) PGPSecretKeyRing secretKey = generator.ed25519x25519Key(userId, null); Iterator iterator = secretKey.getSecretKeys(); - PGPSecretKey primaryKey = iterator.next(); - PGPSecretKey signingSubkey = iterator.next(); - PGPSecretKey encryptionSubkey = iterator.next(); + PGPSecretKey primaryKey = (PGPSecretKey)iterator.next(); + PGPSecretKey signingSubkey = (PGPSecretKey)iterator.next(); + PGPSecretKey encryptionSubkey = (PGPSecretKey)iterator.next(); isFalse("Unexpected key", iterator.hasNext()); isEquals(PublicKeyAlgorithmTags.Ed25519, primaryKey.getPublicKey().getAlgorithm()); Iterator keySignatures = primaryKey.getPublicKey().getKeySignatures(); - PGPSignature directKeySignature = keySignatures.next(); + PGPSignature directKeySignature = (PGPSignature)keySignatures.next(); isFalse(keySignatures.hasNext()); PGPSignatureSubpacketVector hashedSubpackets = directKeySignature.getHashedSubPackets(); isEquals(KeyFlags.CERTIFY_OTHER, hashedSubpackets.getKeyFlags()); @@ -268,13 +271,13 @@ private void testGenerateEd25519x25519Key(APIProvider apiProvider) isEquals(userId, userIds.next()); isFalse(userIds.hasNext()); Iterator userIdSignatures = primaryKey.getPublicKey().getSignaturesForID(userId); - PGPSignature userIdSig = userIdSignatures.next(); + PGPSignature userIdSig = (PGPSignature)userIdSignatures.next(); isFalse(userIdSignatures.hasNext()); isEquals(PGPSignature.POSITIVE_CERTIFICATION, userIdSig.getSignatureType()); isEquals(PublicKeyAlgorithmTags.Ed25519, signingSubkey.getPublicKey().getAlgorithm()); Iterator signingSubkeySigs = signingSubkey.getPublicKey().getKeySignatures(); - PGPSignature signingSubkeySig = signingSubkeySigs.next(); + PGPSignature signingSubkeySig = (PGPSignature)signingSubkeySigs.next(); isFalse(signingSubkeySigs.hasNext()); isEquals(PGPSignature.SUBKEY_BINDING, signingSubkeySig.getSignatureType()); hashedSubpackets = signingSubkeySig.getHashedSubPackets(); @@ -282,7 +285,7 @@ private void testGenerateEd25519x25519Key(APIProvider apiProvider) isEquals(PublicKeyAlgorithmTags.X25519, encryptionSubkey.getPublicKey().getAlgorithm()); Iterator encryptionSubkeySigs = encryptionSubkey.getPublicKey().getKeySignatures(); - PGPSignature encryptionSubkeySig = encryptionSubkeySigs.next(); + PGPSignature encryptionSubkeySig = (PGPSignature)encryptionSubkeySigs.next(); isFalse(encryptionSubkeySigs.hasNext()); isEquals(PGPSignature.SUBKEY_BINDING, encryptionSubkeySig.getSignatureType()); hashedSubpackets = encryptionSubkeySig.getHashedSubPackets(); @@ -299,14 +302,14 @@ private void testGenerateEd448x448Key(APIProvider apiProvider) PGPSecretKeyRing secretKey = generator.ed448x448Key(userId, null); Iterator iterator = secretKey.getSecretKeys(); - PGPSecretKey primaryKey = iterator.next(); - PGPSecretKey signingSubkey = iterator.next(); - PGPSecretKey encryptionSubkey = iterator.next(); + PGPSecretKey primaryKey = (PGPSecretKey)iterator.next(); + PGPSecretKey signingSubkey = (PGPSecretKey)iterator.next(); + PGPSecretKey encryptionSubkey = (PGPSecretKey)iterator.next(); isFalse("Unexpected key", iterator.hasNext()); isEquals(PublicKeyAlgorithmTags.Ed448, primaryKey.getPublicKey().getAlgorithm()); Iterator keySignatures = primaryKey.getPublicKey().getKeySignatures(); - PGPSignature directKeySignature = keySignatures.next(); + PGPSignature directKeySignature = (PGPSignature)keySignatures.next(); isFalse(keySignatures.hasNext()); PGPSignatureSubpacketVector hashedSubpackets = directKeySignature.getHashedSubPackets(); isEquals(KeyFlags.CERTIFY_OTHER, hashedSubpackets.getKeyFlags()); @@ -315,13 +318,13 @@ private void testGenerateEd448x448Key(APIProvider apiProvider) isEquals(userId, userIds.next()); isFalse(userIds.hasNext()); Iterator userIdSignatures = primaryKey.getPublicKey().getSignaturesForID(userId); - PGPSignature userIdSig = userIdSignatures.next(); + PGPSignature userIdSig = (PGPSignature)userIdSignatures.next(); isFalse(userIdSignatures.hasNext()); isEquals(PGPSignature.POSITIVE_CERTIFICATION, userIdSig.getSignatureType()); isEquals(PublicKeyAlgorithmTags.Ed448, signingSubkey.getPublicKey().getAlgorithm()); Iterator signingSubkeySigs = signingSubkey.getPublicKey().getKeySignatures(); - PGPSignature signingSubkeySig = signingSubkeySigs.next(); + PGPSignature signingSubkeySig = (PGPSignature)signingSubkeySigs.next(); isFalse(signingSubkeySigs.hasNext()); isEquals(PGPSignature.SUBKEY_BINDING, signingSubkeySig.getSignatureType()); hashedSubpackets = signingSubkeySig.getHashedSubPackets(); @@ -329,7 +332,7 @@ private void testGenerateEd448x448Key(APIProvider apiProvider) isEquals(PublicKeyAlgorithmTags.X448, encryptionSubkey.getPublicKey().getAlgorithm()); Iterator encryptionSubkeySigs = encryptionSubkey.getPublicKey().getKeySignatures(); - PGPSignature encryptionSubkeySig = encryptionSubkeySigs.next(); + PGPSignature encryptionSubkeySig = (PGPSignature)encryptionSubkeySigs.next(); isFalse(encryptionSubkeySigs.hasNext()); isEquals(PGPSignature.SUBKEY_BINDING, encryptionSubkeySig.getSignatureType()); hashedSubpackets = encryptionSubkeySig.getHashedSubPackets(); @@ -404,13 +407,13 @@ public PGPKeyPair generateFrom(PGPKeyPairGenerator generator) .build(); Iterator keyIt = secretKey.getSecretKeys(); - PGPSecretKey primaryKey = keyIt.next(); + PGPSecretKey primaryKey = (PGPSecretKey)keyIt.next(); isEquals("Primary key MUST be RSA_GENERAL", PublicKeyAlgorithmTags.RSA_GENERAL, primaryKey.getPublicKey().getAlgorithm()); isEquals("Primary key MUST be 4096 bits", 4096, primaryKey.getPublicKey().getBitStrength()); isEquals("Primary key creation time mismatch", creationTime, primaryKey.getPublicKey().getCreationTime()); - PGPSignature directKeySig = primaryKey.getPublicKey().getKeySignatures().next(); + PGPSignature directKeySig = (PGPSignature)primaryKey.getPublicKey().getKeySignatures().next(); PGPSignatureSubpacketVector hashedSubpackets = directKeySig.getHashedSubPackets(); isEquals("Primary key key flags mismatch", KeyFlags.CERTIFY_OTHER, hashedSubpackets.getKeyFlags()); @@ -421,18 +424,18 @@ public PGPKeyPair generateFrom(PGPKeyPairGenerator generator) hashedSubpackets.getNotationDataOccurrences("notation@example.com")[0].getNotationValue()); Iterator uids = primaryKey.getUserIDs(); - String uid = uids.next(); + String uid = (String)uids.next(); isFalse("Unexpected additional UID", uids.hasNext()); - PGPSignature uidSig = primaryKey.getPublicKey().getSignaturesForID(uid).next(); + PGPSignature uidSig = (PGPSignature)primaryKey.getPublicKey().getSignaturesForID(uid).next(); isEquals("UID binding sig type mismatch", PGPSignature.DEFAULT_CERTIFICATION, uidSig.getSignatureType()); - PGPSecretKey signingSubkey = keyIt.next(); + PGPSecretKey signingSubkey = (PGPSecretKey)keyIt.next(); isEquals("Subkey MUST be Ed448", PublicKeyAlgorithmTags.Ed448, signingSubkey.getPublicKey().getAlgorithm()); isEquals("Subkey creation time mismatch", creationTime, signingSubkey.getPublicKey().getCreationTime()); - PGPSignature sigSubBinding = signingSubkey.getPublicKey().getKeySignatures().next(); + PGPSignature sigSubBinding = (PGPSignature)signingSubkey.getPublicKey().getKeySignatures().next(); PGPSignatureSubpacketVector sigSubBindHashPkts = sigSubBinding.getHashedSubPackets(); isEquals("Encryption subkey key flags mismatch", KeyFlags.SIGN_DATA, sigSubBindHashPkts.getKeyFlags()); @@ -442,13 +445,13 @@ public PGPKeyPair generateFrom(PGPKeyPairGenerator generator) isFalse("Missing embedded primary key binding signature", sigSubBindHashPkts.getEmbeddedSignatures().isEmpty()); - PGPSecretKey encryptionSubkey = keyIt.next(); + PGPSecretKey encryptionSubkey = (PGPSecretKey)keyIt.next(); isFalse("Unexpected additional subkey", keyIt.hasNext()); isEquals("Subkey MUST be X448", PublicKeyAlgorithmTags.X448, encryptionSubkey.getPublicKey().getAlgorithm()); isEquals("Subkey creation time mismatch", creationTime, encryptionSubkey.getPublicKey().getCreationTime()); - PGPSignature encryptionBinding = encryptionSubkey.getPublicKey().getKeySignatures().next(); + PGPSignature encryptionBinding = (PGPSignature)encryptionSubkey.getPublicKey().getKeySignatures().next(); PGPSignatureSubpacketVector encBindHashPkts = encryptionBinding.getHashedSubPackets(); isEquals("Encryption subkey key flags mismatch", KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, encBindHashPkts.getKeyFlags()); diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/OperatorBcTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/OperatorBcTest.java index 382a5707c8..6e210590c3 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/test/OperatorBcTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/test/OperatorBcTest.java @@ -59,6 +59,7 @@ import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor; import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor; import org.bouncycastle.openpgp.operator.PGPContentVerifier; +import org.bouncycastle.openpgp.operator.PGPDataEncryptorBuilder; import org.bouncycastle.openpgp.operator.PGPDigestCalculator; import org.bouncycastle.openpgp.operator.PGPDigestCalculatorProvider; import org.bouncycastle.openpgp.operator.bc.BcAEADSecretKeyEncryptorBuilder; @@ -89,7 +90,6 @@ import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.util.test.SimpleTest; import org.bouncycastle.util.test.UncloseableOutputStream; -import org.junit.Assert; public class OperatorBcTest extends SimpleTest @@ -206,7 +206,7 @@ else if (algorithmName.equals("X25519")) BcPublicKeyKeyEncryptionMethodGenerator methodGenerator = new BcPublicKeyKeyEncryptionMethodGenerator(pgpKeyPair.getPublicKey()); - BcPGPDataEncryptorBuilder v6 = new BcPGPDataEncryptorBuilder(symAlgId).setUseV6AEAD().setWithAEAD(AEADAlgorithmTags.OCB, 8); + BcPGPDataEncryptorBuilder v6 = (BcPGPDataEncryptorBuilder)new BcPGPDataEncryptorBuilder(symAlgId).setUseV6AEAD().setWithAEAD(AEADAlgorithmTags.OCB, 8); byte[] sessionKey = PGPUtil.makeRandomKey(symAlgId, new SecureRandom()); PublicKeyEncSessionPacket packet = (PublicKeyEncSessionPacket)methodGenerator.generate(v6, sessionKey); BcPublicKeyDataDecryptorFactory decryptorFactory = new BcPublicKeyDataDecryptorFactory(pgpKeyPair.getPrivateKey()); @@ -242,7 +242,7 @@ private void v5PBEKeyEncryptionMethodGenerator() int symAlgId = SymmetricKeyAlgorithmTags.CAMELLIA_128; BcPBEKeyEncryptionMethodGenerator methodGenerator = new BcPBEKeyEncryptionMethodGenerator("password".toCharArray()); byte[] sessionKey = PGPUtil.makeRandomKey(symAlgId, new SecureRandom()); - BcPGPDataEncryptorBuilder v5 = new BcPGPDataEncryptorBuilder(symAlgId).setUseV5AEAD().setWithAEAD(AEADAlgorithmTags.OCB, 10); + PGPDataEncryptorBuilder v5 = new BcPGPDataEncryptorBuilder(symAlgId).setUseV5AEAD().setWithAEAD(AEADAlgorithmTags.OCB, 10); SymmetricKeyEncSessionPacket packet = (SymmetricKeyEncSessionPacket)methodGenerator.generate(v5, sessionKey); BcPBEDataDecryptorFactory pbeDataDecryptorFactory = new BcPBEDataDecryptorFactory("password".toCharArray(), new BcPGPDigestCalculatorProvider()); byte[] key = pbeDataDecryptorFactory.makeKeyFromPassPhrase(packet.getEncAlgorithm(), packet.getS2K()); @@ -257,7 +257,7 @@ private void v6PBEKeyEncryptionMethodGenerator() BcPBEKeyEncryptionMethodGenerator methodGenerator = new BcPBEKeyEncryptionMethodGenerator("password".toCharArray()); byte[] sessionKey = PGPUtil.makeRandomKey(symAlgId, new SecureRandom()); - BcPGPDataEncryptorBuilder v6 = new BcPGPDataEncryptorBuilder(symAlgId).setUseV6AEAD().setWithAEAD(AEADAlgorithmTags.OCB, 10); + PGPDataEncryptorBuilder v6 = new BcPGPDataEncryptorBuilder(symAlgId).setUseV6AEAD().setWithAEAD(AEADAlgorithmTags.OCB, 10); SymmetricKeyEncSessionPacket packet = (SymmetricKeyEncSessionPacket)methodGenerator.generate(v6, sessionKey); BcPBEDataDecryptorFactory pbeDataDecryptorFactory = new BcPBEDataDecryptorFactory("password".toCharArray(), new BcPGPDigestCalculatorProvider()); byte[] key = pbeDataDecryptorFactory.makeKeyFromPassPhrase(packet.getEncAlgorithm(), packet.getS2K()); @@ -800,8 +800,10 @@ public void testBcAEADSecretKeyEncryptorBuilder() AsymmetricCipherKeyPair kp = gen.generateKeyPair(); Date creationTime = new Date(); SecureRandom random = new SecureRandom(); - for (int version : new int[]{PublicKeyPacket.VERSION_4, PublicKeyPacket.VERSION_6}) + int[] versions = {PublicKeyPacket.VERSION_4, PublicKeyPacket.VERSION_6}; + for (int i = 0; i != versions.length; i++) { + int version = versions[i]; PGPKeyPair keyPair = new BcPGPKeyPair(version, PublicKeyAlgorithmTags.Ed25519, kp, creationTime); BcAEADSecretKeyEncryptorBuilder bcEncBuilder = new BcAEADSecretKeyEncryptorBuilder( @@ -822,7 +824,7 @@ public void testBcAEADSecretKeyEncryptorBuilder() byte[] input2 = Arrays.copyOfRange(input1, 32, 64); byte[] output1 = encryptor.encryptKeyData(key, input1, 32, 32); byte[] output2 = encryptor.encryptKeyData(key, input2, 0, 32); - Assert.assertTrue(Arrays.areEqual(output1, output2)); + isTrue(Arrays.areEqual(output1, output2)); } } diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyPairGeneratorTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyPairGeneratorTest.java index faba05ac49..1c16c272d8 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyPairGeneratorTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/test/PGPKeyPairGeneratorTest.java @@ -79,13 +79,13 @@ private void testGenerateV4RsaKey(Factory factory) PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_4, creationTime); PGPKeyPair kp = gen.generateRsaKeyPair(3072); - isEquals("Key version mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key version mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getVersion(), PublicKeyPacket.VERSION_4); - isEquals("Key algorithm mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key algorithm mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getAlgorithm(), PublicKeyAlgorithmTags.RSA_GENERAL); - isEquals("Key bit-strength mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key bit-strength mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getBitStrength(), 3072); - isEquals("Key creation time mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key creation time mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getCreationTime(), creationTime); } @@ -96,13 +96,13 @@ private void testGenerateV6RsaKey(Factory factory) PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_6, creationTime); PGPKeyPair kp = gen.generateRsaKeyPair(4096); - isEquals("Key version mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key version mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getVersion(), PublicKeyPacket.VERSION_6); - isEquals("Key algorithm mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key algorithm mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getAlgorithm(), PublicKeyAlgorithmTags.RSA_GENERAL); - isEquals("Key bit-strength mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key bit-strength mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getBitStrength(), 4096); - isEquals("Key creation time mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key creation time mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getCreationTime(), creationTime); } @@ -113,13 +113,13 @@ private void testGenerateV6Ed25519Key(Factory factory) PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_6, creationTime); PGPKeyPair kp = gen.generateEd25519KeyPair(); - isEquals("Key version mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key version mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getVersion(), PublicKeyPacket.VERSION_6); - isEquals("Key algorithm mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key algorithm mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getAlgorithm(), PublicKeyAlgorithmTags.Ed25519); - // isEquals("Key bit-strength mismatch (" + gen.getClass().getSimpleName() + ")", + // isEquals("Key bit-strength mismatch (" + gen.getClass().getName() + ")", // kp.getPublicKey().getBitStrength(), Ed25519PublicBCPGKey.LENGTH * 8); - isEquals("Key creation time mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key creation time mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getCreationTime(), creationTime); } @@ -131,13 +131,13 @@ private void testGenerateV4Ed25519Key(Factory factory) PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_4, creationTime); PGPKeyPair kp = gen.generateEd25519KeyPair(); - isEquals("Key version mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key version mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getVersion(), PublicKeyPacket.VERSION_4); - isEquals("Key algorithm mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key algorithm mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getAlgorithm(), PublicKeyAlgorithmTags.Ed25519); - // isEquals("Key bit-strength mismatch (" + gen.getClass().getSimpleName() + ")", + // isEquals("Key bit-strength mismatch (" + gen.getClass().getName() + ")", // kp.getPublicKey().getBitStrength(), Ed25519PublicBCPGKey.LENGTH * 8); - isEquals("Key creation time mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key creation time mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getCreationTime(), creationTime); } @@ -148,13 +148,13 @@ private void testGenerateV6Ed448Key(Factory factory) PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_6, creationTime); PGPKeyPair kp = gen.generateEd448KeyPair(); - isEquals("Key version mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key version mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getVersion(), PublicKeyPacket.VERSION_6); - isEquals("Key algorithm mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key algorithm mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getAlgorithm(), PublicKeyAlgorithmTags.Ed448); - // isEquals("Key bit-strength mismatch (" + gen.getClass().getSimpleName() + ")", + // isEquals("Key bit-strength mismatch (" + gen.getClass().getName() + ")", // kp.getPublicKey().getBitStrength(), Ed448PublicBCPGKey.LENGTH * 8); - isEquals("Key creation time mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key creation time mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getCreationTime(), creationTime); } @@ -165,13 +165,13 @@ private void testGenerateV4Ed448Key(Factory factory) PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_4, creationTime); PGPKeyPair kp = gen.generateEd448KeyPair(); - isEquals("Key version mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key version mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getVersion(), PublicKeyPacket.VERSION_4); - isEquals("Key algorithm mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key algorithm mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getAlgorithm(), PublicKeyAlgorithmTags.Ed448); - // isEquals("Key bit-strength mismatch (" + gen.getClass().getSimpleName() + ")", + // isEquals("Key bit-strength mismatch (" + gen.getClass().getName() + ")", // kp.getPublicKey().getBitStrength(), Ed448PublicBCPGKey.LENGTH * 8); - isEquals("Key creation time mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key creation time mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getCreationTime(), creationTime); } @@ -182,13 +182,13 @@ private void testGenerateV6X25519Key(Factory factory) PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_6, creationTime); PGPKeyPair kp = gen.generateX25519KeyPair(); - isEquals("Key version mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key version mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getVersion(), PublicKeyPacket.VERSION_6); - isEquals("Key algorithm mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key algorithm mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getAlgorithm(), PublicKeyAlgorithmTags.X25519); - // isEquals("Key bit-strength mismatch (" + gen.getClass().getSimpleName() + ")", + // isEquals("Key bit-strength mismatch (" + gen.getClass().getName() + ")", // kp.getPublicKey().getBitStrength(), X25519PublicBCPGKey.LENGTH * 8); - isEquals("Key creation time mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key creation time mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getCreationTime(), creationTime); } @@ -199,13 +199,13 @@ private void testGenerateV4X25519Key(Factory factory) PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_4, creationTime); PGPKeyPair kp = gen.generateX25519KeyPair(); - isEquals("Key version mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key version mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getVersion(), PublicKeyPacket.VERSION_4); - isEquals("Key algorithm mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key algorithm mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getAlgorithm(), PublicKeyAlgorithmTags.X25519); - // isEquals("Key bit-strength mismatch (" + gen.getClass().getSimpleName() + ")", + // isEquals("Key bit-strength mismatch (" + gen.getClass().getName() + ")", // kp.getPublicKey().getBitStrength(), X25519PublicBCPGKey.LENGTH * 8); - isEquals("Key creation time mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key creation time mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getCreationTime(), creationTime); } @@ -216,13 +216,13 @@ private void testGenerateV6X448Key(Factory factory) PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_6, creationTime); PGPKeyPair kp = gen.generateX448KeyPair(); - isEquals("Key version mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key version mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getVersion(), PublicKeyPacket.VERSION_6); - isEquals("Key algorithm mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key algorithm mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getAlgorithm(), PublicKeyAlgorithmTags.X448); - // isEquals("Key bit-strength mismatch (" + gen.getClass().getSimpleName() + ")", + // isEquals("Key bit-strength mismatch (" + gen.getClass().getName() + ")", // kp.getPublicKey().getBitStrength(), X448PublicBCPGKey.LENGTH * 8); - isEquals("Key creation time mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key creation time mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getCreationTime(), creationTime); } @@ -233,13 +233,13 @@ private void testGenerateV4X448Key(Factory factory) PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_4, creationTime); PGPKeyPair kp = gen.generateX448KeyPair(); - isEquals("Key version mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key version mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getVersion(), PublicKeyPacket.VERSION_4); - isEquals("Key algorithm mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key algorithm mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getAlgorithm(), PublicKeyAlgorithmTags.X448); - // isEquals("Key bit-strength mismatch (" + gen.getClass().getSimpleName() + ")", + // isEquals("Key bit-strength mismatch (" + gen.getClass().getName() + ")", // kp.getPublicKey().getBitStrength(), X448PublicBCPGKey.LENGTH * 8); - isEquals("Key creation time mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key creation time mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getCreationTime(), creationTime); } @@ -251,13 +251,13 @@ private void testGenerateV4LegacyEd215519Key(Factory factory) PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_4, creationTime); PGPKeyPair kp = gen.generateLegacyEd25519KeyPair(); - isEquals("Key version mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key version mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getVersion(), PublicKeyPacket.VERSION_4); - isEquals("Key algorithm mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key algorithm mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getAlgorithm(), PublicKeyAlgorithmTags.EDDSA_LEGACY); - // isEquals("Key bit-strength mismatch (" + gen.getClass().getSimpleName() + ")", + // isEquals("Key bit-strength mismatch (" + gen.getClass().getName() + ")", // kp.getPublicKey().getBitStrength(), Ed25519PublicBCPGKey.LENGTH * 8); - isEquals("Key creation time mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key creation time mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getCreationTime(), creationTime); } @@ -266,7 +266,7 @@ private void testGenerateV6LegacyEd25519KeyFails(Factory factory) Date creationTime = currentTimeRounded(); final PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_6, creationTime); isNotNull( - "Expected exception when attempting to generate v6 LegacyEd25519 key with (" + gen.getClass().getSimpleName() + ")", + "Expected exception when attempting to generate v6 LegacyEd25519 key with (" + gen.getClass().getName() + ")", testException( "An implementation MUST NOT generate a v6 LegacyEd25519 key pair.", "PGPException", @@ -286,7 +286,7 @@ private void testGenerateV6LegacyX25519KeyFails(Factory factory) Date creationTime = currentTimeRounded(); final PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_6, creationTime); isNotNull( - "Expected exception when attempting to generate v6 LegacyX25519 key with (" + gen.getClass().getSimpleName() + ")", + "Expected exception when attempting to generate v6 LegacyX25519 key with (" + gen.getClass().getName() + ")", testException( "An implementation MUST NOT generate a v6 LegacyX25519 key pair.", "PGPException", @@ -308,13 +308,13 @@ private void testGenerateV4LegacyX215519Key(Factory factory) PGPKeyPairGenerator gen = factory.create(PublicKeyPacket.VERSION_4, creationTime); PGPKeyPair kp = gen.generateLegacyX25519KeyPair(); - isEquals("Key version mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key version mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getVersion(), PublicKeyPacket.VERSION_4); - isEquals("Key algorithm mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key algorithm mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getAlgorithm(), PublicKeyAlgorithmTags.ECDH); - // isEquals("Key bit-strength mismatch (" + gen.getClass().getSimpleName() + ")", + // isEquals("Key bit-strength mismatch (" + gen.getClass().getName() + ")", // kp.getPublicKey().getBitStrength(), X25519PublicBCPGKey.LENGTH * 8); - isEquals("Key creation time mismatch (" + gen.getClass().getSimpleName() + ")", + isEquals("Key creation time mismatch (" + gen.getClass().getName() + ")", kp.getPublicKey().getCreationTime(), creationTime); } diff --git a/pg/src/test/java/org/bouncycastle/openpgp/test/PGPv6KeyTest.java b/pg/src/test/java/org/bouncycastle/openpgp/test/PGPv6KeyTest.java index 47b3bf3eb4..f9e49da04d 100644 --- a/pg/src/test/java/org/bouncycastle/openpgp/test/PGPv6KeyTest.java +++ b/pg/src/test/java/org/bouncycastle/openpgp/test/PGPv6KeyTest.java @@ -4,7 +4,6 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; -import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Date; import java.util.Iterator; @@ -42,6 +41,7 @@ import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider; import org.bouncycastle.openpgp.operator.bc.BcPGPKeyPair; import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; +import org.bouncycastle.util.Strings; import org.bouncycastle.util.encoders.Hex; public class PGPv6KeyTest @@ -288,14 +288,14 @@ private void testJcaFingerprintCalculation() private void parseProtectedKeyTest() throws IOException, PGPException { - ByteArrayInputStream bIn = new ByteArrayInputStream(ARMORED_PROTECTED_KEY.getBytes(StandardCharsets.UTF_8)); + ByteArrayInputStream bIn = new ByteArrayInputStream(Strings.toUTF8ByteArray(ARMORED_PROTECTED_KEY)); ArmoredInputStream aIn = new ArmoredInputStream(bIn); BCPGInputStream pIn = new BCPGInputStream(aIn); PGPSecretKeyRing secretKeys = new PGPSecretKeyRing(pIn, fingerPrintCalculator); Iterator sIt = secretKeys.getSecretKeys(); - PGPSecretKey key = sIt.next(); + PGPSecretKey key = (PGPSecretKey)sIt.next(); isEncodingEqual("Primary key fingerprint mismatch", PRIMARY_FINGERPRINT, key.getFingerprint()); isEquals("Primary key ID mismatch", PRIMARY_KEYID, key.getKeyID()); isEquals("Primary key algorithm mismatch", @@ -310,7 +310,7 @@ private void parseProtectedKeyTest() isEncodingEqual("Primary key S2K salt mismatch", Hex.decode("5d6fd71c9e096d1eb6917b6e6e1eecae"), key.getS2K().getIV()); - key = sIt.next(); + key = (PGPSecretKey)sIt.next(); isEncodingEqual("Subkey fingerprint mismatch", SUBKEY_FINGERPRINT, key.getFingerprint()); isEquals("Subkey ID mismatch", SUBKEY_KEYID, key.getKeyID()); isEquals("Subkey algorithm mismatch", diff --git a/pkix/src/main/java/org/bouncycastle/cms/jcajce/CMSInputAEADDecryptor.java b/pkix/src/main/java/org/bouncycastle/cms/jcajce/CMSInputAEADDecryptor.java index 814cb568c2..f0405d365e 100644 --- a/pkix/src/main/java/org/bouncycastle/cms/jcajce/CMSInputAEADDecryptor.java +++ b/pkix/src/main/java/org/bouncycastle/cms/jcajce/CMSInputAEADDecryptor.java @@ -2,6 +2,8 @@ import java.io.InputStream; import java.io.OutputStream; +import java.security.AccessController; +import java.security.PrivilegedAction; import javax.crypto.Cipher; @@ -38,7 +40,12 @@ public InputStream getInputStream(InputStream dataIn) public OutputStream getAADStream() { - return new JceAADStream(dataCipher); + if (checkForAEAD()) + { + return new JceAADStream(dataCipher); + } + + return null; // TODO: okay this is awful, we could use AEADParameterSpec for earlier JDKs. } public byte[] getMAC() @@ -49,4 +56,23 @@ public byte[] getMAC() } return null; } + + private static boolean checkForAEAD() + { + return (Boolean)AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + try + { + return Cipher.class.getMethod("updateAAD", byte[].class) != null; + } + catch (Exception ignore) + { + // TODO[logging] Log the fact that we are falling back to BC-specific class + return Boolean.FALSE; + } + } + }); + } } diff --git a/pkix/src/main/jdk1.4/org/bouncycastle/cms/jcajce/CMSInputAEADDecryptor.java b/pkix/src/main/jdk1.4/org/bouncycastle/cms/jcajce/CMSInputAEADDecryptor.java new file mode 100644 index 0000000000..56a900466c --- /dev/null +++ b/pkix/src/main/jdk1.4/org/bouncycastle/cms/jcajce/CMSInputAEADDecryptor.java @@ -0,0 +1,54 @@ +package org.bouncycastle.cms.jcajce; + +import java.io.InputStream; +import java.io.OutputStream; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import javax.crypto.Cipher; + +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.cms.InputStreamWithMAC; +import org.bouncycastle.jcajce.io.CipherInputStream; +import org.bouncycastle.operator.InputAEADDecryptor; + +class CMSInputAEADDecryptor + implements InputAEADDecryptor +{ + private final AlgorithmIdentifier contentEncryptionAlgorithm; + + private final Cipher dataCipher; + + private InputStream inputStream; + + CMSInputAEADDecryptor(AlgorithmIdentifier contentEncryptionAlgorithm, Cipher dataCipher) + { + this.contentEncryptionAlgorithm = contentEncryptionAlgorithm; + this.dataCipher = dataCipher; + } + + public AlgorithmIdentifier getAlgorithmIdentifier() + { + return contentEncryptionAlgorithm; + } + + public InputStream getInputStream(InputStream dataIn) + { + inputStream = dataIn; + return new CipherInputStream(dataIn, dataCipher); + } + + public OutputStream getAADStream() + { + return null; // TODO: okay this is awful, we could use AEADParameterSpec for earlier JDKs. + } + + public byte[] getMAC() + { + if (inputStream instanceof InputStreamWithMAC) + { + return ((InputStreamWithMAC)inputStream).getMAC(); + } + return null; + } +} diff --git a/pkix/src/test/java/org/bouncycastle/cms/test/NewSignedDataTest.java b/pkix/src/test/java/org/bouncycastle/cms/test/NewSignedDataTest.java index 79179e502d..948d194eb5 100644 --- a/pkix/src/test/java/org/bouncycastle/cms/test/NewSignedDataTest.java +++ b/pkix/src/test/java/org/bouncycastle/cms/test/NewSignedDataTest.java @@ -3256,7 +3256,7 @@ public void testEU() { System.setProperty("org.bouncycastle.asn1.allow_wrong_oid_enc", "true"); CMSSignedData cmsSignedData = new CMSSignedData(this.getInput("bc1639test.p7m")); - System.clearProperty("org.bouncycastle.asn1.allow_wrong_oid_enc"); + System.setProperty("org.bouncycastle.asn1.allow_wrong_oid_enc", "false"); } public void testMSPKCS7() throws Exception diff --git a/pkix/src/test/jdk1.4/org/bouncycastle/cms/test/PQCSignedDataTest.java b/pkix/src/test/jdk1.4/org/bouncycastle/cms/test/PQCSignedDataTest.java new file mode 100644 index 0000000000..373810ff68 --- /dev/null +++ b/pkix/src/test/jdk1.4/org/bouncycastle/cms/test/PQCSignedDataTest.java @@ -0,0 +1,445 @@ +package org.bouncycastle.cms.test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.Security; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.bc.BCObjectIdentifiers; +import org.bouncycastle.asn1.cms.Attribute; +import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.cms.CMSAttributes; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.asn1.cms.SignerInfo; +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaCertStore; +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.CMSProcessableByteArray; +import org.bouncycastle.cms.CMSSignedData; +import org.bouncycastle.cms.CMSSignedDataGenerator; +import org.bouncycastle.cms.CMSTypedData; +import org.bouncycastle.cms.SignerId; +import org.bouncycastle.cms.SignerInformation; +import org.bouncycastle.cms.SignerInformationStore; +import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; +import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.DigestCalculatorProvider; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; +import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider; +import org.bouncycastle.util.Store; + +public class PQCSignedDataTest + extends TestCase +{ + private static final String BC = BouncyCastleProvider.PROVIDER_NAME; + private static final String BCPQC = BouncyCastlePQCProvider.PROVIDER_NAME; + + boolean DEBUG = true; + + private static String _origDN; + private static KeyPair _origKP; + private static X509Certificate _origCert; + + private static KeyPair _origFalconKP; + private static X509Certificate _origFalconCert; + private static KeyPair _origPicnicKP; + private static X509Certificate _origPicnicCert; + private static KeyPair _origMlDsaKP; + private static X509Certificate _origMlDsaCert; + private static KeyPair _origSlhDsaKP; + private static X509Certificate _origSlhDsaCert; + + private static String _signDN; + private static KeyPair _signKP; + private static X509Certificate _signCert; + private static KeyPair _signFalconKP; + private static X509Certificate _signFalconCert; + private static KeyPair _signPicnicKP; + private static X509Certificate _signPicnicCert; + private static KeyPair _signMlDsaKP; + private static X509Certificate _signMlDsaCert; + private static KeyPair _signSlhDsaKP; + private static X509Certificate _signSlhDsaCert; + + private static boolean _initialised = false; + + private static final Set noParams = new HashSet(); + + static + { + noParams.add(BCObjectIdentifiers.sphincs256_with_SHA512); + noParams.add(BCObjectIdentifiers.sphincs256_with_SHA3_512); + } + + public PQCSignedDataTest(String name) + { + super(name); + } + + public static void main(String args[]) + throws Exception + { + init(); + + junit.textui.TestRunner.run(PQCSignedDataTest.class); + } + + public static Test suite() + throws Exception + { + init(); + + return new CMSTestSetup(new TestSuite(PQCSignedDataTest.class)); + } + + public void setUp() + throws Exception + { + init(); + } + + private static void init() + throws Exception + { + if (!_initialised) + { + _initialised = true; + + if (Security.getProvider(BC) == null) + { + Security.addProvider(new BouncyCastleProvider()); + } + if (Security.getProvider(BCPQC) == null) + { + Security.addProvider(new BouncyCastlePQCProvider()); + } + + _origDN = "O=Bouncy Castle, C=AU"; + _origKP = PQCTestUtil.makeKeyPair(); + _origCert = PQCTestUtil.makeCertificate(_origKP, _origDN, _origKP, _origDN); + + _signDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU"; + _signKP = PQCTestUtil.makeKeyPair(); + _signCert = PQCTestUtil.makeCertificate(_signKP, _signDN, _origKP, _origDN); + + _origFalconKP = PQCTestUtil.makeFalconKeyPair(); + _origFalconCert = PQCTestUtil.makeCertificate(_origFalconKP, _origDN, _origFalconKP, _origDN); + + _signFalconKP = PQCTestUtil.makeFalconKeyPair(); + _signFalconCert = PQCTestUtil.makeCertificate(_signFalconKP, _signDN, _origFalconKP, _origDN); + + _origPicnicKP = PQCTestUtil.makePicnicKeyPair(); + _origPicnicCert = PQCTestUtil.makeCertificate(_origPicnicKP, _origDN, _origPicnicKP, _origDN); + + _signPicnicKP = PQCTestUtil.makePicnicKeyPair(); + _signPicnicCert = PQCTestUtil.makeCertificate(_signPicnicKP, _signDN, _origPicnicKP, _origDN); + + _origMlDsaKP = PQCTestUtil.makeMlDsaKeyPair(); + _origMlDsaCert = PQCTestUtil.makeCertificate(_origMlDsaKP, _origDN, _origMlDsaKP, _origDN); + + _signMlDsaKP = PQCTestUtil.makeMlDsaKeyPair(); + _signMlDsaCert = PQCTestUtil.makeCertificate(_signMlDsaKP, _signDN, _origMlDsaKP, _origDN); + + _origSlhDsaKP = PQCTestUtil.makeSlhDsaKeyPair(); + _origSlhDsaCert = PQCTestUtil.makeCertificate(_origSlhDsaKP, _origDN, _origSlhDsaKP, _origDN); + + _signSlhDsaKP = PQCTestUtil.makeSlhDsaKeyPair(); + _signSlhDsaCert = PQCTestUtil.makeCertificate(_signSlhDsaKP, _signDN, _origSlhDsaKP, _origDN); + } + } + + public void testSPHINCS256Encapsulated() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origCert); + certList.add(_signCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("SHA512withSPHINCS256").setProvider(BCPQC).build(_origKP.getPrivate()), _origCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, true); + + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certs = s.getCertificates(); + + SignerInformationStore signers = s.getSignerInfos(); + + Collection c = signers.getSigners(); + Iterator it = c.iterator(); + SignerId sid = null; + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certs.getMatches(signer.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(cert))); + + // + // check content digest + // + + byte[] contentDigest = (byte[])gen.getGeneratedDigests().get(signer.getDigestAlgOID()); + + AttributeTable table = signer.getSignedAttributes(); + Attribute hash = table.get(CMSAttributes.messageDigest); + + assertTrue(MessageDigest.isEqual(contentDigest, ((ASN1OctetString)hash.getAttrValues().getObjectAt(0)).getOctets())); + } + } + + public void testFalconEncapsulated() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origFalconCert); + certList.add(_signFalconCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("Falcon-512").setProvider(BCPQC).build(_origFalconKP.getPrivate()), _origFalconCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, true); + + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certs = s.getCertificates(); + + SignerInformationStore signers = s.getSignerInfos(); + + Collection c = signers.getSigners(); + Iterator it = c.iterator(); + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certs.getMatches(signer.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(cert))); + + // + // check content digest + // + + byte[] contentDigest = (byte[])gen.getGeneratedDigests().get(signer.getDigestAlgOID()); + + AttributeTable table = signer.getSignedAttributes(); + Attribute hash = table.get(CMSAttributes.messageDigest); + + assertTrue(MessageDigest.isEqual(contentDigest, ((ASN1OctetString)hash.getAttrValues().getObjectAt(0)).getOctets())); + } + } + + public void testPicnicEncapsulated() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origPicnicCert); + certList.add(_signPicnicCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("PICNIC").setProvider(BCPQC).build(_origPicnicKP.getPrivate()), _origPicnicCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, true); + + checkSignature(s, gen); + } + + public void testMLDSAEncapsulated() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origMlDsaCert); + certList.add(_signMlDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("ML-DSA").setProvider(BC).build(_origMlDsaKP.getPrivate()), _origMlDsaCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, true); + + checkSignature(s, gen); + } + + public void testHashMLDSAEncapsulated() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origMlDsaCert); + certList.add(_signMlDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("HASH-ML-DSA").setProvider(BC).build(_origMlDsaKP.getPrivate()), _origMlDsaCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, true); + + checkSignature(s, gen); + } + + public void testSLHDSAEncapsulated() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origSlhDsaCert); + certList.add(_signSlhDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("SLH-DSA").setProvider(BC).build(_origSlhDsaKP.getPrivate()), _origSlhDsaCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, true); + + checkSignature(s, gen); + } + + public void testHashSLHDSAEncapsulated() + throws Exception + { + List certList = new ArrayList(); + CMSTypedData msg = new CMSProcessableByteArray("Hello World!".getBytes()); + + certList.add(_origSlhDsaCert); + certList.add(_signSlhDsaCert); + + Store certs = new JcaCertStore(certList); + + CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); + + DigestCalculatorProvider digCalcProv = new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(); + + gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(digCalcProv).build(new JcaContentSignerBuilder("HASH-SLH-DSA").setProvider(BC).build(_origSlhDsaKP.getPrivate()), _origSlhDsaCert)); + + gen.addCertificates(certs); + + CMSSignedData s = gen.generate(msg, true); + + checkSignature(s, gen); + } + + private void checkSignature(CMSSignedData s, CMSSignedDataGenerator gen) + throws IOException, CMSException, OperatorCreationException, CertificateException + { + Store certs; + ByteArrayInputStream bIn = new ByteArrayInputStream(s.getEncoded()); + ASN1InputStream aIn = new ASN1InputStream(bIn); + + s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + + certs = s.getCertificates(); + + SignerInformationStore signers = s.getSignerInfos(); + + Collection c = signers.getSigners(); + Iterator it = c.iterator(); + + + while (it.hasNext()) + { + SignerInformation signer = (SignerInformation)it.next(); + Collection certCollection = certs.getMatches(signer.getSID()); + + Iterator certIt = certCollection.iterator(); + X509CertificateHolder cert = (X509CertificateHolder)certIt.next(); + + cert.getSubjectPublicKeyInfo(); + + assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(cert))); + + // + // check content digest + // + + byte[] contentDigest = (byte[])gen.getGeneratedDigests().get(signer.getDigestAlgOID()); + + AttributeTable table = signer.getSignedAttributes(); + Attribute hash = table.get(CMSAttributes.messageDigest); + + assertTrue(MessageDigest.isEqual(contentDigest, ((ASN1OctetString)hash.getAttrValues().getObjectAt(0)).getOctets())); + } + } +} diff --git a/pkix/src/test/jdk1.4/org/bouncycastle/cms/test/PQCTestUtil.java b/pkix/src/test/jdk1.4/org/bouncycastle/cms/test/PQCTestUtil.java new file mode 100644 index 0000000000..30547c4b04 --- /dev/null +++ b/pkix/src/test/jdk1.4/org/bouncycastle/cms/test/PQCTestUtil.java @@ -0,0 +1,132 @@ +package org.bouncycastle.cms.test; + +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.Date; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.KeyPurposeId; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.jcajce.interfaces.MLDSAKey; +import org.bouncycastle.jcajce.interfaces.SLHDSAKey; +import org.bouncycastle.jcajce.spec.MLDSAParameterSpec; +import org.bouncycastle.jcajce.spec.SLHDSAParameterSpec; +import org.bouncycastle.jce.X509KeyUsage; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.pqc.jcajce.interfaces.FalconKey; +import org.bouncycastle.pqc.jcajce.interfaces.PicnicKey; +import org.bouncycastle.pqc.jcajce.spec.FalconParameterSpec; +import org.bouncycastle.pqc.jcajce.spec.PicnicParameterSpec; +import org.bouncycastle.pqc.jcajce.spec.SPHINCS256KeyGenParameterSpec; +import org.bouncycastle.pqc.jcajce.spec.SPHINCSPlusParameterSpec; + +public class PQCTestUtil +{ + public static KeyPair makeKeyPair() + throws Exception + { + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("SPHINCS256", "BCPQC"); + + kpGen.initialize(new SPHINCS256KeyGenParameterSpec(), new SecureRandom()); + + return kpGen.generateKeyPair(); + } + + public static KeyPair makeSphincsPlusKeyPair() + throws Exception + { + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("SPHINCSPlus", "BCPQC"); + + kpGen.initialize(SPHINCSPlusParameterSpec.sha2_128f_robust, new SecureRandom()); + + return kpGen.generateKeyPair(); + } + + public static KeyPair makeFalconKeyPair() + throws Exception + { + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("Falcon", "BCPQC"); + + kpGen.initialize(FalconParameterSpec.falcon_512, new SecureRandom()); + + return kpGen.generateKeyPair(); + } + + public static KeyPair makePicnicKeyPair() + throws Exception + { + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("Picnic", "BCPQC"); + //TODO: divide into two with cases with digest and with parametersets + kpGen.initialize(PicnicParameterSpec.picnicl1full, new SecureRandom()); + + return kpGen.generateKeyPair(); + } + + public static KeyPair makeMlDsaKeyPair() + throws Exception + { + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("ML-DSA", "BC"); + //TODO: divide into two with cases with digest and with parametersets + kpGen.initialize(MLDSAParameterSpec.ml_dsa_65, new SecureRandom()); + + return kpGen.generateKeyPair(); + } + + public static KeyPair makeSlhDsaKeyPair() + throws Exception + { + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("SLH-DSA", "BC"); + //TODO: divide into two with cases with digest and with parametersets + kpGen.initialize(SLHDSAParameterSpec.slh_dsa_sha2_128f, new SecureRandom()); + + return kpGen.generateKeyPair(); + } + + public static X509Certificate makeCertificate(KeyPair subKP, String subDN, KeyPair issKP, String issDN) + throws Exception + { + // + // create base certificate - version 3 + // + ContentSigner sigGen; + PrivateKey issPriv = issKP.getPrivate(); + if (issPriv instanceof FalconKey) + { + sigGen = new JcaContentSignerBuilder(((FalconKey)issPriv).getParameterSpec().getName()).setProvider("BCPQC").build(issPriv); + } + else if (issPriv instanceof PicnicKey) + { +// sigGen = new JcaContentSignerBuilder(((PicnicKey)issPriv).getParameterSpec().getName()).setProvider("BCPQC").build(issPriv); + sigGen = new JcaContentSignerBuilder("PICNIC").setProvider("BCPQC").build(issPriv); + } + else if (issPriv instanceof MLDSAKey) + { + sigGen = new JcaContentSignerBuilder("ML-DSA").setProvider("BC").build(issPriv); + } + else if (issPriv instanceof SLHDSAKey) + { + sigGen = new JcaContentSignerBuilder("SLH-DSA").setProvider("BC").build(issPriv); + } + else + { + sigGen = new JcaContentSignerBuilder("SHA512withSPHINCS256").setProvider("BCPQC").build(issPriv); + } + + X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(new X500Name(issDN), BigInteger.valueOf(1), new Date(System.currentTimeMillis() - 50000), new Date(System.currentTimeMillis() + 50000), new X500Name(subDN), subKP.getPublic()) + .addExtension(new ASN1ObjectIdentifier("2.5.29.15"), true, + new X509KeyUsage(X509KeyUsage.digitalSignature)) + .addExtension(new ASN1ObjectIdentifier("2.5.29.37"), true, + new DERSequence(KeyPurposeId.anyExtendedKeyUsage)); + + return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen)); + } +} diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/compositesignatures/KeyFactorySpi.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/compositesignatures/KeyFactorySpi.java index 7a3dfe850c..7d30e3e0a7 100644 --- a/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/compositesignatures/KeyFactorySpi.java +++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/compositesignatures/KeyFactorySpi.java @@ -32,6 +32,7 @@ import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; +import org.bouncycastle.asn1.util.ASN1Dump; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x9.X962Parameters; @@ -44,8 +45,11 @@ import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter; import org.bouncycastle.jcajce.util.BCJcaJceHelper; import org.bouncycastle.jcajce.util.JcaJceHelper; +import org.bouncycastle.math.ec.rfc8032.Ed25519; +import org.bouncycastle.math.ec.rfc8032.Ed448; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Exceptions; +import org.bouncycastle.util.encoders.Hex; /** * KeyFactory for composite signatures. List of supported combinations is in CompositeSignaturesConstants @@ -69,6 +73,7 @@ public class KeyFactorySpi private static final AlgorithmIdentifier ecDsaBrainpoolP384r1 = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, new X962Parameters(TeleTrusTObjectIdentifiers.brainpoolP384r1)); private static Map pairings = new HashMap(); + private static Map componentKeySizes = new HashMap(); static { @@ -101,6 +106,36 @@ public class KeyFactorySpi pairings.put(MiscObjectIdentifiers.id_HashMLDSA87_ECDSA_P384_SHA512, new AlgorithmIdentifier[]{mlDsa87, ecDsaP384}); pairings.put(MiscObjectIdentifiers.id_HashMLDSA87_ECDSA_brainpoolP384r1_SHA512, new AlgorithmIdentifier[]{mlDsa87, ecDsaBrainpoolP384r1}); pairings.put(MiscObjectIdentifiers.id_HashMLDSA87_Ed448_SHA512, new AlgorithmIdentifier[] { mlDsa87, ed448}); + + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA44_RSA2048_PSS_SHA256, new int[]{1328, 268}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA44_RSA2048_PKCS15_SHA256, new int[]{1312, 284}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA44_Ed25519_SHA512, new int[]{1312, Ed25519.PUBLIC_KEY_SIZE}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256, new int[]{1312, 76}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA65_RSA3072_PSS_SHA256, new int[]{1952, 256}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA65_RSA3072_PKCS15_SHA256, new int[]{1952, 256}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA65_RSA4096_PSS_SHA384, new int[]{1952, 542}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA65_RSA4096_PKCS15_SHA384, new int[]{1952, 542}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA65_ECDSA_P384_SHA384, new int[]{1952, 87}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA65_ECDSA_brainpoolP256r1_SHA256, new int[]{1952, 76}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA65_Ed25519_SHA512, new int[]{1952, Ed25519.PUBLIC_KEY_SIZE}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA87_ECDSA_P384_SHA384, new int[]{2592, 87}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA87_ECDSA_brainpoolP384r1_SHA384, new int[]{2592, 87}); + componentKeySizes.put(MiscObjectIdentifiers.id_MLDSA87_Ed448_SHA512, new int[]{2592, Ed448.PUBLIC_KEY_SIZE}); + + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA44_RSA2048_PSS_SHA256, new int[]{1328, 268}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA44_RSA2048_PKCS15_SHA256, new int[]{1312, 284}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA44_Ed25519_SHA512, new int[]{1312, Ed25519.PUBLIC_KEY_SIZE}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA44_ECDSA_P256_SHA256, new int[]{1312, 76}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA65_RSA3072_PSS_SHA512, new int[]{1952, 256}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA65_RSA3072_PKCS15_SHA512, new int[]{1952, 256}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA65_RSA4096_PSS_SHA512, new int[]{1952, 542}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA65_RSA4096_PKCS15_SHA512, new int[]{1952, 542}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA65_ECDSA_P384_SHA512, new int[]{1952, 87}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA65_ECDSA_brainpoolP256r1_SHA512, new int[]{1952, 76}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA65_Ed25519_SHA512, new int[]{1952, Ed25519.PUBLIC_KEY_SIZE}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA87_ECDSA_P384_SHA512, new int[]{2592, 87}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA87_ECDSA_brainpoolP384r1_SHA512, new int[]{2592, 87}); + componentKeySizes.put(MiscObjectIdentifiers.id_HashMLDSA87_Ed448_SHA512, new int[] { 2592, Ed448.PUBLIC_KEY_SIZE}); } private JcaJceHelper helper; @@ -267,10 +302,22 @@ public PublicKey generatePublic(SubjectPublicKeyInfo keyInfo) { helper = new BCJcaJceHelper(); } - - ASN1Sequence seq = DERSequence.getInstance(keyInfo.getPublicKeyData().getBytes()); + System.err.println(ASN1Dump.dumpAsString(keyInfo, true)); ASN1ObjectIdentifier keyIdentifier = keyInfo.getAlgorithm().getAlgorithm(); - + + ASN1Sequence seq = null; + byte[][] componentKeys = new byte[2][]; + + try + { + seq = DERSequence.getInstance(keyInfo.getPublicKeyData().getBytes()); + } + catch (Exception e) + { + componentKeys = split(keyIdentifier, keyInfo.getPublicKeyData()); + System.err.println(Hex.toHexString(componentKeys[1])); + } + if (MiscObjectIdentifiers.id_alg_composite.equals(keyIdentifier) || MiscObjectIdentifiers.id_composite_key.equals(keyIdentifier)) { @@ -296,27 +343,36 @@ public PublicKey generatePublic(SubjectPublicKeyInfo keyInfo) try { + int numKeys = (seq == null) ? componentKeys.length : seq.size(); + List factories = getKeyFactoriesFromIdentifier(keyIdentifier); - ASN1BitString[] componentBitStrings = new ASN1BitString[seq.size()]; - for (int i = 0; i < seq.size(); i++) + ASN1BitString[] componentBitStrings = new ASN1BitString[numKeys]; + for (int i = 0; i < numKeys; i++) { // Check if component is OCTET STRING. If yes, convert it to BIT STRING. // This check should not be necessary since the draft RFC specifies components as BIT STRING encoded, // but currently the example public keys are OCTET STRING. So we leave it for interoperability. - if (seq.getObjectAt(i) instanceof DEROctetString) + if (seq != null) { - componentBitStrings[i] = new DERBitString(((DEROctetString)seq.getObjectAt(i)).getOctets()); + if (seq.getObjectAt(i) instanceof DEROctetString) + { + componentBitStrings[i] = new DERBitString(((DEROctetString)seq.getObjectAt(i)).getOctets()); + } + else + { + componentBitStrings[i] = (DERBitString)seq.getObjectAt(i); + } } else { - componentBitStrings[i] = (DERBitString)seq.getObjectAt(i); + componentBitStrings[i] = new DERBitString(componentKeys[i]); } } // We need to get X509EncodedKeySpec to use key factories to produce component public keys. X509EncodedKeySpec[] x509EncodedKeySpecs = getKeysSpecs(keyIdentifier, componentBitStrings); - PublicKey[] publicKeys = new PublicKey[seq.size()]; - for (int i = 0; i < seq.size(); i++) + PublicKey[] publicKeys = new PublicKey[numKeys]; + for (int i = 0; i < numKeys; i++) { publicKeys[i] = factories.get(i).generatePublic(x509EncodedKeySpecs[i]); } @@ -329,6 +385,21 @@ public PublicKey generatePublic(SubjectPublicKeyInfo keyInfo) } } + byte[][] split(ASN1ObjectIdentifier algorithm, ASN1BitString publicKeyData) + { + int[] sizes = componentKeySizes.get(algorithm); + byte[] keyData = publicKeyData.getOctets(); + byte[][] components = new byte[][] { new byte[sizes[0]], new byte[sizes[1]] }; + + System.out.println(keyData.length + " " + (sizes[0] + sizes[1]) + " " + (keyData.length - sizes[0])); + System.arraycopy(keyData, 0, components[0], 0, sizes[0]); + System.arraycopy(keyData, sizes[0], components[1], 0, sizes[1]); + System.out.println("keydata: " + Hex.toHexString(keyData)); + System.out.println("part1: " + Hex.toHexString(components[0])); + System.out.println("part2: " + Hex.toHexString(components[1])); + return components; + } + /** * A helper method that returns a list of KeyFactory objects based on the composite signature OID. * diff --git a/prov/src/main/java/org/bouncycastle/pqc/jcajce/provider/util/WrapUtil.java b/prov/src/main/java/org/bouncycastle/pqc/jcajce/provider/util/WrapUtil.java index 8e91981ff2..7d1f11900b 100644 --- a/prov/src/main/java/org/bouncycastle/pqc/jcajce/provider/util/WrapUtil.java +++ b/prov/src/main/java/org/bouncycastle/pqc/jcajce/provider/util/WrapUtil.java @@ -100,7 +100,7 @@ private static byte[] makeKeyBytes(KTSParameterSpec ktsSpec, byte[] secret) } catch (IllegalArgumentException e) { - throw new InvalidKeyException(e.getMessage(), e); + throw new InvalidKeyException(e.getMessage()); } } } diff --git a/prov/src/main/jdk1.4/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java b/prov/src/main/jdk1.4/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java index 6df1bf6d2d..41ed06db8b 100644 --- a/prov/src/main/jdk1.4/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java +++ b/prov/src/main/jdk1.4/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPrivateKey.java @@ -46,23 +46,28 @@ public class BCECPrivateKey implements ECPrivateKey, PKCS12BagAttributeCarrier, ECPointEncoder { - private String algorithm = "EC"; - private boolean withCompression; + static final long serialVersionUID = 994553197664784084L; - private transient BigInteger d; - private transient ECParameterSpec ecSpec; - private transient ProviderConfiguration configuration; - private transient ASN1BitString publicKey; + private String algorithm = "EC"; + private boolean withCompression; + + private transient BigInteger d; + private transient ECParameterSpec ecSpec; + private transient ProviderConfiguration configuration; + private transient ASN1BitString publicKey; + private transient PrivateKeyInfo privateKeyInfo; + private transient byte[] encoding; private transient ECPrivateKeyParameters baseKey; private transient PKCS12BagAttributeCarrierImpl attrCarrier = new PKCS12BagAttributeCarrierImpl(); + protected BCECPrivateKey() { } - BCECPrivateKey( - ECPrivateKey key, + public BCECPrivateKey( + ECPrivateKey key, ProviderConfiguration configuration) { this.d = key.getD(); @@ -73,8 +78,8 @@ protected BCECPrivateKey() } public BCECPrivateKey( - String algorithm, - ECPrivateKeySpec spec, + String algorithm, + ECPrivateKeySpec spec, ProviderConfiguration configuration) { this.algorithm = algorithm; @@ -83,12 +88,26 @@ public BCECPrivateKey( this.configuration = configuration; this.baseKey = convertToBaseKey(this); } + + public BCECPrivateKey( + String algorithm, + BCECPrivateKey key) + { + this.algorithm = algorithm; + this.d = key.d; + this.ecSpec = key.ecSpec; + this.withCompression = key.withCompression; + this.attrCarrier = key.attrCarrier; + this.publicKey = key.publicKey; + this.configuration = key.configuration; + this.baseKey = key.baseKey; + } public BCECPrivateKey( - String algorithm, - ECPrivateKeyParameters params, - BCECPublicKey pubKey, - ECParameterSpec spec, + String algorithm, + ECPrivateKeyParameters params, + BCECPublicKey pubKey, + ECParameterSpec spec, ProviderConfiguration configuration) { ECDomainParameters dp = params.getParameters(); @@ -116,49 +135,26 @@ public BCECPrivateKey( } public BCECPrivateKey( - String algorithm, - ECPrivateKeyParameters params, - ProviderConfiguration configuration) + String algorithm, + ECPrivateKeyParameters params, + ProviderConfiguration configuration) { this.algorithm = algorithm; this.d = params.getD(); this.ecSpec = null; this.configuration = configuration; - this.baseKey = convertToBaseKey(this); - } - - public BCECPrivateKey( - String algorithm, - BCECPrivateKey key) - { - this.algorithm = algorithm; - this.d = key.d; - this.ecSpec = key.ecSpec; - this.withCompression = key.withCompression; - this.publicKey = key.publicKey; - this.attrCarrier = key.attrCarrier; - this.configuration = key.configuration; - } - - BCECPrivateKey( - PrivateKeyInfo info, - ProviderConfiguration configuration) - throws IOException - { - this.configuration = configuration; - - populateFromPrivKeyInfo(info); + this.baseKey = params; } BCECPrivateKey( - String algorithm, - PrivateKeyInfo info, + String algorithm, + PrivateKeyInfo info, ProviderConfiguration configuration) throws IOException { + this.algorithm = algorithm; this.configuration = configuration; populateFromPrivKeyInfo(info); - this.algorithm = algorithm; } private void populateFromPrivKeyInfo(PrivateKeyInfo info) @@ -306,6 +302,16 @@ public Enumeration getBagAttributeKeys() return attrCarrier.getBagAttributeKeys(); } + public boolean hasFriendlyName() + { + return attrCarrier.hasFriendlyName(); + } + + public void setFriendlyName(String friendlyName) + { + attrCarrier.setFriendlyName(friendlyName); + } + public void setPointFormat(String style) { withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style)); diff --git a/prov/src/main/jdk1.4/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java b/prov/src/main/jdk1.4/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java index 344dbe4280..8c2c701cfd 100644 --- a/prov/src/main/jdk1.4/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java +++ b/prov/src/main/jdk1.4/org/bouncycastle/jcajce/provider/asymmetric/ecgost/BCECGOST3410PrivateKey.java @@ -47,10 +47,10 @@ public class BCECGOST3410PrivateKey implements ECPrivateKey, PKCS12BagAttributeCarrier, ECPointEncoder { - private String algorithm = "ECGOST3410"; - private boolean withCompression; + private String algorithm = "ECGOST3410"; + private boolean withCompression; - private transient BigInteger d; + private transient BigInteger d; private transient ECParameterSpec ecSpec; private transient ASN1BitString publicKey; private transient PKCS12BagAttributeCarrierImpl attrCarrier = new PKCS12BagAttributeCarrierImpl(); @@ -60,7 +60,7 @@ protected BCECGOST3410PrivateKey() } BCECGOST3410PrivateKey( - ECPrivateKey key) + ECPrivateKey key) { this.d = key.getD(); this.algorithm = key.getAlgorithm(); @@ -68,19 +68,19 @@ protected BCECGOST3410PrivateKey() } public BCECGOST3410PrivateKey( - ECPrivateKeySpec spec) + ECPrivateKeySpec spec) { this.d = spec.getD(); this.ecSpec = spec.getParams(); } public BCECGOST3410PrivateKey( - String algorithm, - ECPrivateKeyParameters params, - BCECGOST3410PublicKey pubKey, - ECParameterSpec spec) + String algorithm, + ECPrivateKeyParameters params, + BCECGOST3410PublicKey pubKey, + ECParameterSpec spec) { - ECDomainParameters dp = params.getParameters(); + ECDomainParameters dp = params.getParameters(); this.algorithm = algorithm; this.d = params.getD(); @@ -88,11 +88,11 @@ public BCECGOST3410PrivateKey( if (spec == null) { this.ecSpec = new ECParameterSpec( - dp.getCurve(), - dp.getG(), - dp.getN(), - dp.getH(), - dp.getSeed()); + dp.getCurve(), + dp.getG(), + dp.getN(), + dp.getH(), + dp.getSeed()); } else { @@ -103,8 +103,8 @@ public BCECGOST3410PrivateKey( } public BCECGOST3410PrivateKey( - String algorithm, - ECPrivateKeyParameters params) + String algorithm, + ECPrivateKeyParameters params) { this.algorithm = algorithm; this.d = params.getD(); @@ -112,8 +112,8 @@ public BCECGOST3410PrivateKey( } public BCECGOST3410PrivateKey( - String algorithm, - BCECGOST3410PrivateKey key) + String algorithm, + BCECGOST3410PrivateKey key) { this.algorithm = algorithm; this.d = key.d; @@ -124,7 +124,7 @@ public BCECGOST3410PrivateKey( } BCECGOST3410PrivateKey( - PrivateKeyInfo info) + PrivateKeyInfo info) throws IOException { populateFromPrivKeyInfo(info); @@ -133,20 +133,20 @@ public BCECGOST3410PrivateKey( private void populateFromPrivKeyInfo(PrivateKeyInfo info) throws IOException { - X962Parameters params = X962Parameters.getInstance(info.getPrivateKeyAlgorithm().getParameters()); + X962Parameters params = X962Parameters.getInstance(info.getPrivateKeyAlgorithm().getParameters()); if (params.isNamedCurve()) { ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters(); - X9ECParameters ecP = ECGOST3410NamedCurves.getByOIDX9(oid); + X9ECParameters ecP = ECGOST3410NamedCurves.getByOIDX9(oid); ecSpec = new ECNamedCurveParameterSpec( - ECUtil.getCurveName(oid), - ecP.getCurve(), - ecP.getG(), - ecP.getN(), - ecP.getH(), - ecP.getSeed()); + ECUtil.getCurveName(oid), + ecP.getCurve(), + ecP.getG(), + ecP.getN(), + ecP.getH(), + ecP.getSeed()); } else if (params.isImplicitlyCA()) { @@ -154,23 +154,23 @@ else if (params.isImplicitlyCA()) } else { - X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); + X9ECParameters ecP = X9ECParameters.getInstance(params.getParameters()); ecSpec = new ECParameterSpec(ecP.getCurve(), - ecP.getG(), - ecP.getN(), - ecP.getH(), - ecP.getSeed()); + ecP.getG(), + ecP.getN(), + ecP.getH(), + ecP.getSeed()); } if (info.parsePrivateKey() instanceof ASN1Integer) { - ASN1Integer derD = ASN1Integer.getInstance(info.parsePrivateKey()); + ASN1Integer derD = ASN1Integer.getInstance(info.parsePrivateKey()); this.d = derD.getValue(); } else { - ECPrivateKeyStructure ec = new ECPrivateKeyStructure(ASN1Sequence.getInstance(info.parsePrivateKey())); + ECPrivateKeyStructure ec = new ECPrivateKeyStructure(ASN1Sequence.getInstance(info.parsePrivateKey())); this.d = ec.getKey(); this.publicKey = ec.getPublicKey(); @@ -200,14 +200,14 @@ public String getFormat() */ public byte[] getEncoded() { - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ASN1OutputStream dOut = ASN1OutputStream.create(bOut, ASN1Encoding.DER); - X962Parameters params = null; + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ASN1OutputStream dOut = ASN1OutputStream.create(bOut, ASN1Encoding.DER); + X962Parameters params = null; if (ecSpec instanceof ECNamedCurveParameterSpec) { ASN1ObjectIdentifier curveOid = ECUtil.getNamedCurveOid(((ECNamedCurveParameterSpec)ecSpec).getName()); - + params = new X962Parameters(curveOid); } else if (ecSpec == null) @@ -222,16 +222,16 @@ else if (ecSpec == null) ECPoint g = pG.getCurve().createPoint(pG.getAffineXCoord().toBigInteger(), pG.getAffineYCoord().toBigInteger()); X9ECParameters ecP = new X9ECParameters( - p.getCurve(), - new X9ECPoint(g, withCompression), - p.getN(), - p.getH(), - p.getSeed()); + p.getCurve(), + new X9ECPoint(g, withCompression), + p.getN(), + p.getH(), + p.getSeed()); params = new X962Parameters(ecP); } - PrivateKeyInfo info; + PrivateKeyInfo info; ECPrivateKeyStructure keyStructure; if (publicKey != null) @@ -271,7 +271,7 @@ public ECParameterSpec getParameters() { return (ECParameterSpec)ecSpec; } - + public BigInteger getD() { return d; @@ -279,7 +279,7 @@ public BigInteger getD() public void setBagAttribute( ASN1ObjectIdentifier oid, - ASN1Encodable attribute) + ASN1Encodable attribute) { attrCarrier.setBagAttribute(oid, attribute); } @@ -294,10 +294,20 @@ public Enumeration getBagAttributeKeys() { return attrCarrier.getBagAttributeKeys(); } - + + public boolean hasFriendlyName() + { + return attrCarrier.hasFriendlyName(); + } + + public void setFriendlyName(String friendlyName) + { + attrCarrier.setFriendlyName(friendlyName); + } + public void setPointFormat(String style) { - withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style)); + withCompression = !("UNCOMPRESSED".equalsIgnoreCase(style)); } ECParameterSpec engineGetSpec() @@ -332,7 +342,7 @@ public int hashCode() return getD().hashCode() ^ engineGetSpec().hashCode(); } - private ASN1BitString getPublicKeyDetails(BCECGOST3410PublicKey pub) + private ASN1BitString getPublicKeyDetails(BCECGOST3410PublicKey pub) { try { diff --git a/prov/src/main/jdk1.4/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java b/prov/src/main/jdk1.4/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java index 25c201ed61..d461361cd9 100644 --- a/prov/src/main/jdk1.4/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java +++ b/prov/src/main/jdk1.4/org/bouncycastle/jcajce/provider/symmetric/util/BaseBlockCipher.java @@ -24,20 +24,19 @@ import javax.crypto.spec.RC5ParameterSpec; import org.bouncycastle.asn1.DEROctetString; -import org.bouncycastle.crypto.fpe.FPEEngine; -import org.bouncycastle.crypto.fpe.FPEFF1Engine; -import org.bouncycastle.crypto.fpe.FPEFF3_1Engine; -import org.bouncycastle.crypto.params.FPEParameters; -import org.bouncycastle.internal.asn1.cms.GCMParameters; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.BufferedBlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.CryptoServicesRegistrar; import org.bouncycastle.crypto.DataLengthException; +import org.bouncycastle.crypto.DefaultBufferedBlockCipher; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.engines.DSTU7624Engine; +import org.bouncycastle.crypto.fpe.FPEEngine; +import org.bouncycastle.crypto.fpe.FPEFF1Engine; +import org.bouncycastle.crypto.fpe.FPEFF3_1Engine; import org.bouncycastle.crypto.modes.AEADBlockCipher; import org.bouncycastle.crypto.modes.AEADCipher; import org.bouncycastle.crypto.modes.CBCBlockCipher; @@ -60,19 +59,24 @@ import org.bouncycastle.crypto.paddings.BlockCipherPadding; import org.bouncycastle.crypto.paddings.ISO10126d2Padding; import org.bouncycastle.crypto.paddings.ISO7816d4Padding; +import org.bouncycastle.crypto.paddings.PKCS7Padding; import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher; import org.bouncycastle.crypto.paddings.TBCPadding; import org.bouncycastle.crypto.paddings.X923Padding; import org.bouncycastle.crypto.paddings.ZeroBytePadding; import org.bouncycastle.crypto.params.AEADParameters; +import org.bouncycastle.crypto.params.FPEParameters; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.crypto.params.ParametersWithSBox; import org.bouncycastle.crypto.params.RC2Parameters; import org.bouncycastle.crypto.params.RC5Parameters; +import org.bouncycastle.internal.asn1.cms.GCMParameters; import org.bouncycastle.jcajce.PBKDF1Key; import org.bouncycastle.jcajce.PBKDF1KeyWithParameters; +import org.bouncycastle.jcajce.PBKDF2Key; +import org.bouncycastle.jcajce.PBKDF2KeyWithParameters; import org.bouncycastle.jcajce.PKCS12Key; import org.bouncycastle.jcajce.PKCS12KeyWithParameters; import org.bouncycastle.jcajce.spec.AEADParameterSpec; @@ -92,7 +96,7 @@ public class BaseBlockCipher // // specs we can handle. // - private Class[] availableSpecs = + private static final Class[] availableSpecs = { RC2ParameterSpec.class, RC5ParameterSpec.class, @@ -155,9 +159,28 @@ protected BaseBlockCipher( cipher = new BufferedGenericBlockCipher(provider.get()); } + protected BaseBlockCipher( + int keySizeInBits, + BlockCipherProvider provider) + { + baseEngine = provider.get(); + engineProvider = provider; + this.keySizeInBits = keySizeInBits; + + cipher = new BufferedGenericBlockCipher(provider.get()); + } + protected BaseBlockCipher( AEADBlockCipher engine) { + this(0, engine); + } + + protected BaseBlockCipher( + int keySizeInBits, + AEADBlockCipher engine) + { + this.keySizeInBits = keySizeInBits; this.baseEngine = engine.getUnderlyingCipher(); if (engine.getAlgorithmName().indexOf("GCM") >= 0) { @@ -186,6 +209,16 @@ protected BaseBlockCipher( boolean fixedIv, int ivLength) { + this(0, engine, fixedIv, ivLength); + } + + protected BaseBlockCipher( + int keySizeInBits, + AEADBlockCipher engine, + boolean fixedIv, + int ivLength) + { + this.keySizeInBits = keySizeInBits; this.baseEngine = engine.getUnderlyingCipher(); this.fixedIv = fixedIv; this.ivLength = ivLength; @@ -199,6 +232,19 @@ protected BaseBlockCipher( this(engine, true, ivLength); } + protected BaseBlockCipher( + int keySizeInBits, + org.bouncycastle.crypto.BlockCipher engine, + int ivLength) + { + this.keySizeInBits = keySizeInBits; + baseEngine = engine; + + this.fixedIv = true; + this.cipher = new BufferedGenericBlockCipher(engine); + this.ivLength = ivLength / 8; + } + protected BaseBlockCipher( org.bouncycastle.crypto.BlockCipher engine, boolean fixedIv, @@ -218,6 +264,19 @@ protected BaseBlockCipher( this(engine, true, ivLength); } + protected BaseBlockCipher( + int keySizeInBits, + BufferedBlockCipher engine, + int ivLength) + { + this.keySizeInBits = keySizeInBits; + baseEngine = engine.getUnderlyingCipher(); + + this.cipher = new BufferedGenericBlockCipher(engine); + this.fixedIv = true; + this.ivLength = ivLength / 8; + } + protected BaseBlockCipher( BufferedBlockCipher engine, boolean fixedIv, @@ -350,7 +409,7 @@ else if (modeName.equals("CBC")) { ivLength = baseEngine.getBlockSize(); cipher = new BufferedGenericBlockCipher( - new CBCBlockCipher(baseEngine)); + CBCBlockCipher.newInstance(baseEngine)); } else if (modeName.startsWith("OFB")) { @@ -376,12 +435,12 @@ else if (modeName.startsWith("CFB")) int wordSize = Integer.parseInt(modeName.substring(3)); cipher = new BufferedGenericBlockCipher( - new CFBBlockCipher(baseEngine, wordSize)); + CFBBlockCipher.newInstance(baseEngine, wordSize)); } else { cipher = new BufferedGenericBlockCipher( - new CFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize())); + CFBBlockCipher.newInstance(baseEngine, 8 * baseEngine.getBlockSize())); } } else if (modeName.startsWith("PGPCFB")) @@ -423,8 +482,8 @@ else if (modeName.equals("SIC")) throw new IllegalArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)"); } fixedIv = false; - cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( - new SICBlockCipher(baseEngine))); + cipher = new BufferedGenericBlockCipher(new DefaultBufferedBlockCipher( + SICBlockCipher.newInstance(baseEngine))); } else if (modeName.equals("CTR")) { @@ -432,31 +491,31 @@ else if (modeName.equals("CTR")) fixedIv = false; if (baseEngine instanceof DSTU7624Engine) { - cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( + cipher = new BufferedGenericBlockCipher(new DefaultBufferedBlockCipher( new KCTRBlockCipher(baseEngine))); } else { - cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( - new SICBlockCipher(baseEngine))); + cipher = new BufferedGenericBlockCipher(new DefaultBufferedBlockCipher( + SICBlockCipher.newInstance(baseEngine))); } } else if (modeName.equals("GOFB")) { ivLength = baseEngine.getBlockSize(); - cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( + cipher = new BufferedGenericBlockCipher(new DefaultBufferedBlockCipher( new GOFBBlockCipher(baseEngine))); } else if (modeName.equals("GCFB")) { ivLength = baseEngine.getBlockSize(); - cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( + cipher = new BufferedGenericBlockCipher(new DefaultBufferedBlockCipher( new GCFBBlockCipher(baseEngine))); } else if (modeName.equals("CTS")) { ivLength = baseEngine.getBlockSize(); - cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(new CBCBlockCipher(baseEngine))); + cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(CBCBlockCipher.newInstance(baseEngine))); } else if (modeName.equals("CCM")) { @@ -467,7 +526,7 @@ else if (modeName.equals("CCM")) } else { - cipher = new AEADGenericBlockCipher(new CCMBlockCipher(baseEngine)); + cipher = new AEADGenericBlockCipher(CCMBlockCipher.newInstance(baseEngine)); } } else if (modeName.equals("OCB")) @@ -505,7 +564,7 @@ else if (modeName.equals("GCM")) else { ivLength = 12; - cipher = new AEADGenericBlockCipher(new GCMBlockCipher(baseEngine)); + cipher = new AEADGenericBlockCipher(GCMBlockCipher.newInstance(baseEngine)); } } else @@ -538,7 +597,7 @@ protected void engineSetPadding( { if (cipher.wrapOnNoPadding()) { - cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(cipher.getUnderlyingCipher())); + cipher = new BufferedGenericBlockCipher(new DefaultBufferedBlockCipher(cipher.getUnderlyingCipher())); } } else if (paddingName.equals("WITHCTS") || paddingName.equals("CTSPADDING") || paddingName.equals("CS3PADDING")) @@ -587,7 +646,7 @@ else if (paddingName.equals("TBCPADDING")) protected void engineInit( int opmode, Key key, - final AlgorithmParameterSpec params, + final AlgorithmParameterSpec paramSpec, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { @@ -609,7 +668,7 @@ protected void engineInit( // // for RC5-64 we must have some default parameters // - if (params == null && (baseEngine != null && baseEngine.getAlgorithmName().startsWith("RC5-64"))) + if (paramSpec == null && (baseEngine != null && baseEngine.getAlgorithmName().startsWith("RC5-64"))) { throw new InvalidAlgorithmParameterException("RC5 requires an RC5ParametersSpec to be passed in."); } @@ -629,9 +688,9 @@ protected void engineInit( throw new InvalidKeyException("PKCS12 requires a SecretKey/PBEKey"); } - if (params instanceof PBEParameterSpec) + if (paramSpec instanceof PBEParameterSpec) { - pbeSpec = (PBEParameterSpec)params; + pbeSpec = (PBEParameterSpec)paramSpec; } if (k instanceof PBEKey && pbeSpec == null) @@ -680,9 +739,9 @@ else if (key instanceof PBKDF1Key) { PBKDF1Key k = (PBKDF1Key)key; - if (params instanceof PBEParameterSpec) + if (paramSpec instanceof PBEParameterSpec) { - pbeSpec = (PBEParameterSpec)params; + pbeSpec = (PBEParameterSpec)paramSpec; } if (k instanceof PBKDF1KeyWithParameters && pbeSpec == null) { @@ -695,6 +754,25 @@ else if (key instanceof PBKDF1Key) ivParam = (ParametersWithIV)param; } } + else if (key instanceof PBKDF2Key) + { + PBKDF2Key k = (PBKDF2Key)key; + + if (paramSpec instanceof PBEParameterSpec) + { + pbeSpec = (PBEParameterSpec)paramSpec; + } + if (k instanceof PBKDF2KeyWithParameters && pbeSpec == null) + { + pbeSpec = new PBEParameterSpec(((PBKDF2KeyWithParameters)k).getSalt(), ((PBKDF2KeyWithParameters)k).getIterationCount()); + } + + param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS5S2, PBE.SHA512, keySizeInBits, 0, pbeSpec, cipher.getAlgorithmName()); + if (param instanceof ParametersWithIV) + { + ivParam = (ParametersWithIV)param; + } + } else if (key instanceof BCPBEKey) { BCPBEKey k = (BCPBEKey)key; @@ -710,12 +788,12 @@ else if (key instanceof BCPBEKey) if (k.getParam() != null) { - param = adjustParameters(params, k.getParam()); + param = adjustParameters(paramSpec, k.getParam()); } - else if (params instanceof PBEParameterSpec) + else if (paramSpec instanceof PBEParameterSpec) { - pbeSpec = (PBEParameterSpec)params; - param = PBE.Util.makePBEParameters(k, params, cipher.getUnderlyingCipher().getAlgorithmName()); + pbeSpec = (PBEParameterSpec)paramSpec; + param = PBE.Util.makePBEParameters(k, paramSpec, cipher.getUnderlyingCipher().getAlgorithmName()); } else { @@ -730,7 +808,7 @@ else if (params instanceof PBEParameterSpec) else if (key instanceof PBEKey) { PBEKey k = (PBEKey)key; - pbeSpec = (PBEParameterSpec)params; + pbeSpec = (PBEParameterSpec)paramSpec; if (k instanceof PKCS12KeyWithParameters && pbeSpec == null) { pbeSpec = new PBEParameterSpec(k.getSalt(), k.getIterationCount()); @@ -755,6 +833,8 @@ else if (!(key instanceof RepeatedSecretKeySpec)) param = null; } + AlgorithmParameterSpec params = paramSpec; + if (params instanceof AEADParameterSpec) { if (!isAEADModeName(modeName) && !(cipher instanceof AEADGenericBlockCipher)) @@ -809,7 +889,7 @@ else if (params instanceof GOST28147ParameterSpec) GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params; param = new ParametersWithSBox( - new KeyParameter(key.getEncoded()), ((GOST28147ParameterSpec)params).getSbox()); + new KeyParameter(key.getEncoded()), ((GOST28147ParameterSpec)params).getSBox()); if (gost28147Param.getIV() != null && ivLength != 0) { @@ -886,9 +966,9 @@ else if (params instanceof FPEParameterSpec) { FPEParameterSpec spec = (FPEParameterSpec)params; - param = new FPEParameters((KeyParameter)param, spec.getRadix(), spec.getTweak(), spec.isUsingInverseFunction()); + param = new FPEParameters((KeyParameter)param, spec.getRadixConverter(), spec.getTweak(), spec.isUsingInverseFunction()); } - else if (gcmSpecClass != null && gcmSpecClass.isInstance(params)) + else if (GcmSpecUtil.isGcmSpec(params)) { if (!isAEADModeName(modeName) && !(cipher instanceof AEADGenericBlockCipher)) { @@ -993,7 +1073,7 @@ else if (params instanceof GOST28147ParameterSpec) // need to pick up IV and SBox. GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params; - param = new ParametersWithSBox(param, gost28147Param.getSbox()); + param = new ParametersWithSBox(param, gost28147Param.getSBox()); if (gost28147Param.getIV() != null && ivLength != 0) { @@ -1016,7 +1096,7 @@ else if (params instanceof GOST28147ParameterSpec) // need to pick up IV and SBox. GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params; - param = new ParametersWithSBox(param, gost28147Param.getSbox()); + param = new ParametersWithSBox(param, gost28147Param.getSBox()); if (gost28147Param.getIV() != null && ivLength != 0) { @@ -1254,7 +1334,7 @@ private static class BufferedGenericBlockCipher BufferedGenericBlockCipher(org.bouncycastle.crypto.BlockCipher cipher) { - this.cipher = new PaddedBufferedBlockCipher(cipher); + this(cipher, new PKCS7Padding()); } BufferedGenericBlockCipher(org.bouncycastle.crypto.BlockCipher cipher, BlockCipherPadding padding) diff --git a/prov/src/test/jdk1.4/org/bouncycastle/jce/provider/test/PBETest.java b/prov/src/test/jdk1.4/org/bouncycastle/jce/provider/test/PBETest.java new file mode 100644 index 0000000000..48c8d38399 --- /dev/null +++ b/prov/src/test/jdk1.4/org/bouncycastle/jce/provider/test/PBETest.java @@ -0,0 +1,824 @@ +package org.bouncycastle.jce.provider.test; + +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.SecureRandom; +import java.security.Security; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.InvalidParameterSpecException; +import java.security.spec.KeySpec; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.bouncycastle.asn1.bc.BCObjectIdentifiers; +import org.bouncycastle.crypto.Digest; +import org.bouncycastle.crypto.PBEParametersGenerator; +import org.bouncycastle.crypto.digests.SHA1Digest; +import org.bouncycastle.crypto.digests.SHA256Digest; +import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator; +import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator; +import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.crypto.params.ParametersWithIV; +import org.bouncycastle.jcajce.PKCS12Key; +import org.bouncycastle.jcajce.PKCS12KeyWithParameters; +import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Strings; +import org.bouncycastle.util.encoders.Hex; +import org.bouncycastle.util.test.FixedSecureRandom; +import org.bouncycastle.util.test.SimpleTest; + +/** + * test out the various PBE modes, making sure the JCE implementations + * are compatible with the light weight ones. + */ +public class PBETest + extends SimpleTest +{ + private static class OpenSSLTest + extends SimpleTest + { + char[] password; + String baseAlgorithm; + String algorithm; + int keySize; + int ivSize; + + OpenSSLTest( + String baseAlgorithm, + String algorithm, + int keySize, + int ivSize) + { + this.password = algorithm.toCharArray(); + this.baseAlgorithm = baseAlgorithm; + this.algorithm = algorithm; + this.keySize = keySize; + this.ivSize = ivSize; + } + + public String getName() + { + return "OpenSSLPBE"; + } + + public void performTest() + throws Exception + { + byte[] salt = new byte[16]; + int iCount = 100; + + for (int i = 0; i != salt.length; i++) + { + salt[i] = (byte)i; + } + + OpenSSLPBEParametersGenerator pGen = new OpenSSLPBEParametersGenerator(); + + pGen.init( + PBEParametersGenerator.PKCS5PasswordToBytes(password), + salt, + iCount); + + ParametersWithIV params = (ParametersWithIV)pGen.generateDerivedParameters(keySize, ivSize); + + SecretKeySpec encKey = new SecretKeySpec(((KeyParameter)params.getParameters()).getKey(), baseAlgorithm); + + Cipher c; + + if (baseAlgorithm.equals("RC4")) + { + c = Cipher.getInstance(baseAlgorithm, "BC"); + + c.init(Cipher.ENCRYPT_MODE, encKey); + } + else + { + c = Cipher.getInstance(baseAlgorithm + "/CBC/PKCS7Padding", "BC"); + + c.init(Cipher.ENCRYPT_MODE, encKey, new IvParameterSpec(params.getIV())); + } + + byte[] enc = c.doFinal(salt); + + c = Cipher.getInstance(algorithm, "BC"); + + PBEKeySpec keySpec = new PBEKeySpec(password, salt, iCount); + SecretKeyFactory fact = SecretKeyFactory.getInstance(algorithm, "BC"); + + c.init(Cipher.DECRYPT_MODE, fact.generateSecret(keySpec)); + + byte[] dec = c.doFinal(enc); + + if (!Arrays.areEqual(salt, dec)) + { + fail("" + algorithm + "failed encryption/decryption test"); + } + } + } + + private static class PKCS12Test + extends SimpleTest + { + char[] password; + String baseAlgorithm; + String algorithm; + Digest digest; + int keySize; + int ivSize; + + PKCS12Test( + String baseAlgorithm, + String algorithm, + Digest digest, + int keySize, + int ivSize) + { + this.password = algorithm.toCharArray(); + this.baseAlgorithm = baseAlgorithm; + this.algorithm = algorithm; + this.digest = digest; + this.keySize = keySize; + this.ivSize = ivSize; + } + + public String getName() + { + return "PKCS12PBE"; + } + + public void performTest() + throws Exception + { + byte[] salt = new byte[digest.getDigestSize()]; + int iCount = 100; + + digest.doFinal(salt, 0); + + PKCS12ParametersGenerator pGen = new PKCS12ParametersGenerator(digest); + + pGen.init( + PBEParametersGenerator.PKCS12PasswordToBytes(password), + salt, + iCount); + + ParametersWithIV params = (ParametersWithIV)pGen.generateDerivedParameters(keySize, ivSize); + + SecretKeySpec encKey = new SecretKeySpec(((KeyParameter)params.getParameters()).getKey(), baseAlgorithm); + + Cipher c; + + if (baseAlgorithm.equals("RC4")) + { + c = Cipher.getInstance(baseAlgorithm, "BC"); + + c.init(Cipher.ENCRYPT_MODE, encKey); + } + else + { + c = Cipher.getInstance(baseAlgorithm + "/CBC/PKCS7Padding", "BC"); + + c.init(Cipher.ENCRYPT_MODE, encKey, new IvParameterSpec(params.getIV())); + } + + byte[] enc = c.doFinal(salt); + + c = Cipher.getInstance(algorithm, "BC"); + + PBEKeySpec keySpec = new PBEKeySpec(password, salt, iCount); + SecretKeyFactory fact = SecretKeyFactory.getInstance(algorithm, "BC"); + + c.init(Cipher.DECRYPT_MODE, fact.generateSecret(keySpec)); + + byte[] dec = c.doFinal(enc); + + if (!Arrays.areEqual(salt, dec)) + { + fail("" + algorithm + "failed encryption/decryption test"); + } + + // + // get the parameters + // + AlgorithmParameters param = checkParameters(c, salt, iCount); + + // + // try using parameters + // + c = Cipher.getInstance(algorithm, "BC"); + + keySpec = new PBEKeySpec(password); + + c.init(Cipher.DECRYPT_MODE, fact.generateSecret(keySpec), param); + + checkParameters(c, salt, iCount); + + dec = c.doFinal(enc); + + if (!Arrays.areEqual(salt, dec)) + { + fail("" + algorithm + "failed encryption/decryption test"); + } + + // + // try using PBESpec + // + c = Cipher.getInstance(algorithm, "BC"); + + keySpec = new PBEKeySpec(password); + + c.init(Cipher.DECRYPT_MODE, fact.generateSecret(keySpec), param.getParameterSpec(PBEParameterSpec.class)); + + checkParameters(c, salt, iCount); + + dec = c.doFinal(enc); + + if (!Arrays.areEqual(salt, dec)) + { + fail("" + algorithm + "failed encryption/decryption test"); + } + } + + private AlgorithmParameters checkParameters(Cipher c, byte[] salt, int iCount) + throws InvalidParameterSpecException + { + AlgorithmParameters param = c.getParameters(); + PBEParameterSpec spec = (PBEParameterSpec)param.getParameterSpec(PBEParameterSpec.class); + + if (!Arrays.areEqual(salt, spec.getSalt())) + { + fail("" + algorithm + "failed salt test"); + } + + if (iCount != spec.getIterationCount()) + { + fail("" + algorithm + "failed count test"); + } + return param; + } + } + + private PKCS12Test[] pkcs12Tests = { + new PKCS12Test("DESede", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC", new SHA1Digest(), 192, 64), + new PKCS12Test("DESede", "PBEWITHSHAAND2-KEYTRIPLEDES-CBC", new SHA1Digest(), 128, 64), + new PKCS12Test("RC4", "PBEWITHSHAAND128BITRC4", new SHA1Digest(), 128, 0), + new PKCS12Test("RC4", "PBEWITHSHAAND40BITRC4", new SHA1Digest(), 40, 0), + new PKCS12Test("RC2", "PBEWITHSHAAND128BITRC2-CBC", new SHA1Digest(), 128, 64), + new PKCS12Test("RC2", "PBEWITHSHAAND40BITRC2-CBC", new SHA1Digest(), 40, 64), + new PKCS12Test("AES", "PBEWithSHA1And128BitAES-CBC-BC", new SHA1Digest(), 128, 128), + new PKCS12Test("AES", "PBEWithSHA1And192BitAES-CBC-BC", new SHA1Digest(), 192, 128), + new PKCS12Test("AES", "PBEWithSHA1And256BitAES-CBC-BC", new SHA1Digest(), 256, 128), + new PKCS12Test("AES", "PBEWithSHA256And128BitAES-CBC-BC", new SHA256Digest(), 128, 128), + new PKCS12Test("AES", "PBEWithSHA256And192BitAES-CBC-BC", new SHA256Digest(), 192, 128), + new PKCS12Test("AES", "PBEWithSHA256And256BitAES-CBC-BC", new SHA256Digest(), 256, 128), + new PKCS12Test("Twofish","PBEWithSHAAndTwofish-CBC", new SHA1Digest(), 256, 128), + new PKCS12Test("IDEA", "PBEWithSHAAndIDEA-CBC", new SHA1Digest(), 128, 64), + new PKCS12Test("AES", BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc.getId(), new SHA1Digest(), 128, 128), + new PKCS12Test("AES", BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc.getId(), new SHA1Digest(), 192, 128), + new PKCS12Test("AES", BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes256_cbc.getId(), new SHA1Digest(), 256, 128), + new PKCS12Test("AES", BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes128_cbc.getId(), new SHA256Digest(), 128, 128), + new PKCS12Test("AES", BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes192_cbc.getId(), new SHA256Digest(), 192, 128), + new PKCS12Test("AES", BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc.getId(), new SHA256Digest(), 256, 128), + }; + + private OpenSSLTest openSSLTests[] = { + new OpenSSLTest("AES", "PBEWITHMD5AND128BITAES-CBC-OPENSSL", 128, 128), + new OpenSSLTest("AES", "PBEWITHMD5AND192BITAES-CBC-OPENSSL", 192, 128), + new OpenSSLTest("AES", "PBEWITHMD5AND256BITAES-CBC-OPENSSL", 256, 128) + }; + + static byte[] message = Hex.decode("4869205468657265"); + + private byte[] hMac1 = Hex.decode("bcc42174ccb04f425d9a5c8c4a95d6fd7c372911"); + private byte[] hMac2 = Hex.decode("cb1d8bdb6aca9e3fa8980d6eb41ab28a7eb2cfd6"); + private byte[] hMac3 = Hex.decode("514aa173a302c770689269aac08eb8698e5879ac"); + private byte[] hMac4 = Hex.decode("d24b4eb0e5bd611d4ca88bd6428d14ee2e004c7e"); + + private Cipher makePBECipherUsingParam( + String algorithm, + int mode, + char[] password, + byte[] salt, + int iterationCount) + throws Exception + { + PBEKeySpec pbeSpec = new PBEKeySpec(password); + SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm, "BC"); + PBEParameterSpec defParams = new PBEParameterSpec(salt, iterationCount); + + Cipher cipher = Cipher.getInstance(algorithm, "BC"); + + cipher.init(mode, keyFact.generateSecret(pbeSpec), defParams); + + return cipher; + } + + private Cipher makePBECipherWithoutParam( + String algorithm, + int mode, + char[] password, + byte[] salt, + int iterationCount) + throws Exception + { + PBEKeySpec pbeSpec = new PBEKeySpec(password, salt, iterationCount); + SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm, "BC"); + + Cipher cipher = Cipher.getInstance(algorithm, "BC"); + + cipher.init(mode, keyFact.generateSecret(pbeSpec)); + + return cipher; + } + + public void testPBEHMac( + String hmacName, + byte[] output) + { + SecretKey key; + byte[] out; + Mac mac; + + try + { + SecretKeyFactory fact = SecretKeyFactory.getInstance(hmacName, "BC"); + + key = fact.generateSecret(new PBEKeySpec("hello".toCharArray())); + + mac = Mac.getInstance(hmacName, "BC"); + } + catch (Exception e) + { + fail("Failed - exception " + e.toString(), e); + return; + } + + try + { + mac.init(key, new PBEParameterSpec(new byte[20], 100)); + } + catch (Exception e) + { + fail("Failed - exception " + e.toString(), e); + return; + } + + mac.reset(); + + mac.update(message, 0, message.length); + + out = mac.doFinal(); + + if (!Arrays.areEqual(out, output)) + { + fail("Failed - expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out))); + } + } + + public void testPKCS12HMac( + String hmacName, + byte[] output) + { + SecretKey key; + byte[] out; + Mac mac; + + try + { + mac = Mac.getInstance(hmacName, "BC"); + } + catch (Exception e) + { + fail("Failed - exception " + e.toString(), e); + return; + } + + try + { + mac.init(new PKCS12Key("hello".toCharArray()), new PBEParameterSpec(new byte[20], 100)); + } + catch (Exception e) + { + fail("Failed - exception " + e.toString(), e); + return; + } + + mac.reset(); + + mac.update(message, 0, message.length); + + out = mac.doFinal(); + + if (!Arrays.areEqual(out, output)) + { + fail("Failed - expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out))); + } + } + + public void testPBEonSecretKeyHmac( + String hmacName, + byte[] output) + { + SecretKey key; + byte[] out; + Mac mac; + + try + { + SecretKeyFactory fact = SecretKeyFactory.getInstance(hmacName, "BC"); + + key = fact.generateSecret(new PBEKeySpec("hello".toCharArray(), new byte[20], 100, 160)); + } + catch (Exception e) + { + fail("Failed - exception " + e.toString(), e); + return; + } + + try + { + mac = Mac.getInstance("HMAC-SHA1", "BC"); + + mac.init(key); + } + catch (Exception e) + { + fail("Failed - exception " + e.toString(), e); + return; + } + + mac.reset(); + + mac.update(message, 0, message.length); + + out = mac.doFinal(); + + if (!Arrays.areEqual(out, output)) + { + fail("Failed - expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(out))); + } + } + + private void testCipherNameWithWrap(String name, String simpleName) + throws Exception + { + KeyGenerator kg = KeyGenerator.getInstance("AES"); + kg.init(new SecureRandom()); + SecretKey key = kg.generateKey(); + + byte[] salt = { + (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c, + (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99 + }; + char[] password = { 'p','a','s','s','w','o','r','d' }; + + PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 20); + PBEKeySpec pbeKeySpec = new PBEKeySpec(password); + SecretKeyFactory keyFac = + SecretKeyFactory.getInstance(name); + SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec); + Cipher pbeEncryptCipher = Cipher.getInstance(name, "BC"); + + pbeEncryptCipher.init(Cipher.WRAP_MODE, pbeKey, pbeParamSpec); + + byte[] symKeyBytes = pbeEncryptCipher.wrap(key); + + Cipher simpleCipher = Cipher.getInstance(simpleName, "BC"); + + simpleCipher.init(Cipher.UNWRAP_MODE, pbeKey, pbeParamSpec); + + SecretKey unwrappedKey = (SecretKey)simpleCipher.unwrap(symKeyBytes, "AES", Cipher.SECRET_KEY); + + if (!Arrays.areEqual(unwrappedKey.getEncoded(), key.getEncoded())) + { + fail("key mismatch on unwrapping"); + } + } + + public void testNullSalt() + throws Exception + { + SecretKeyFactory skf = SecretKeyFactory.getInstance("PBEWITHSHAAND128BITAES-CBC-BC"); + Key key = skf.generateSecret(new PBEKeySpec("secret".toCharArray())); + + Cipher cipher = Cipher.getInstance("PBEWITHSHAAND128BITAES-CBC-BC"); + + try + { + cipher.init(Cipher.ENCRYPT_MODE, key, (AlgorithmParameterSpec)null); + fail("no exception"); + } + catch (InvalidAlgorithmParameterException e) + { + isTrue("wrong message", "PBEKey requires parameters to specify salt".equals(e.getMessage())); + } + } + + + public void performTest() + throws Exception + { + byte[] input = Hex.decode("1234567890abcdefabcdef1234567890fedbca098765"); + + // + // DES + // + Cipher cEnc = Cipher.getInstance("DES/CBC/PKCS7Padding", "BC"); + + cEnc.init(Cipher.ENCRYPT_MODE, + new SecretKeySpec(Hex.decode("30e69252758e5346"), "DES"), + new IvParameterSpec(Hex.decode("7c1c1ab9c454a688"))); + + byte[] out = cEnc.doFinal(input); + + char[] password = { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' }; + + Cipher cDec = makePBECipherUsingParam( + "PBEWithSHA1AndDES", + Cipher.DECRYPT_MODE, + password, + Hex.decode("7d60435f02e9e0ae"), + 2048); + + byte[] in = cDec.doFinal(out); + + if (!Arrays.areEqual(input, in)) + { + fail("DES failed"); + } + + cDec = makePBECipherWithoutParam( + "PBEWithSHA1AndDES", + Cipher.DECRYPT_MODE, + password, + Hex.decode("7d60435f02e9e0ae"), + 2048); + + in = cDec.doFinal(out); + + if (!Arrays.areEqual(input, in)) + { + fail("DES failed without param"); + } + + // + // DESede + // + cEnc = Cipher.getInstance("DESede/CBC/PKCS7Padding", "BC"); + + cEnc.init(Cipher.ENCRYPT_MODE, + new SecretKeySpec(Hex.decode("732f2d33c801732b7206756cbd44f9c1c103ddd97c7cbe8e"), "DES"), + new IvParameterSpec(Hex.decode("b07bf522c8d608b8"))); + + out = cEnc.doFinal(input); + + cDec = makePBECipherUsingParam( + "PBEWithSHAAnd3-KeyTripleDES-CBC", + Cipher.DECRYPT_MODE, + password, + Hex.decode("7d60435f02e9e0ae"), + 2048); + + in = cDec.doFinal(out); + + if (!Arrays.areEqual(input, in)) + { + fail("DESede failed"); + } + + // + // 40Bit RC2 + // + cEnc = Cipher.getInstance("RC2/CBC/PKCS7Padding", "BC"); + + cEnc.init(Cipher.ENCRYPT_MODE, + new SecretKeySpec(Hex.decode("732f2d33c8"), "RC2"), + new IvParameterSpec(Hex.decode("b07bf522c8d608b8"))); + + out = cEnc.doFinal(input); + + cDec = makePBECipherUsingParam( + "PBEWithSHAAnd40BitRC2-CBC", + Cipher.DECRYPT_MODE, + password, + Hex.decode("7d60435f02e9e0ae"), + 2048); + + in = cDec.doFinal(out); + + if (!Arrays.areEqual(input, in)) + { + fail("RC2 failed"); + } + + // + // 128bit RC4 + // + cEnc = Cipher.getInstance("RC4", "BC"); + + cEnc.init(Cipher.ENCRYPT_MODE, + new SecretKeySpec(Hex.decode("732f2d33c801732b7206756cbd44f9c1"), "RC4")); + + out = cEnc.doFinal(input); + + cDec = makePBECipherUsingParam( + "PBEWithSHAAnd128BitRC4", + Cipher.DECRYPT_MODE, + password, + Hex.decode("7d60435f02e9e0ae"), + 2048); + + in = cDec.doFinal(out); + + if (!Arrays.areEqual(input, in)) + { + fail("RC4 failed"); + } + + cDec = makePBECipherWithoutParam( + "PBEWithSHAAnd128BitRC4", + Cipher.DECRYPT_MODE, + password, + Hex.decode("7d60435f02e9e0ae"), + 2048); + + in = cDec.doFinal(out); + + if (!Arrays.areEqual(input, in)) + { + fail("RC4 failed without param"); + } + + for (int i = 0; i != pkcs12Tests.length; i++) + { + pkcs12Tests[i].perform(); + } + + for (int i = 0; i != openSSLTests.length; i++) + { + openSSLTests[i].perform(); + } + + testPKCS12Interop(); + + testPBEHMac("PBEWithHMacSHA1", hMac1); + testPBEHMac("PBEWithHMacRIPEMD160", hMac2); + + testPBEonSecretKeyHmac("PBKDF2WithHmacSHA1", hMac3); + testPBEonSecretKeyHmac("PBKDF2WithHMacSM3", hMac4); + + testCipherNameWithWrap("PBEWITHSHA256AND128BITAES-CBC-BC", "AES/CBC/PKCS5Padding"); + testCipherNameWithWrap("PBEWITHSHAAND40BITRC4", "RC4"); + testCipherNameWithWrap("PBEWITHSHAAND128BITRC4", "RC4"); + + checkPBE("PBKDF2WithHmacSHA1", true, "f14687fc31a66e2f7cc01d0a65f687961bd27e20", "6f6579193d6433a3e4600b243bb390674f04a615"); + + testPKCS12HMac("HMacSHA1", Hex.decode("bcc42174ccb04f425d9a5c8c4a95d6fd7c372911")); + testPKCS12HMac("HMacSHA256", Hex.decode("e1ae77e2d1dcc56a8befa3867ea3ff8c2163b01885504379412e525b120bf9ce")); + testPKCS12HMac("HMacSHA384", Hex.decode("1256a861351db2082f2ba827ca72cede54ee851f533962bba1fd97b500b6d6eb42aa4a51920aca0c817955feaf52d7f8")); + testPKCS12HMac("HMacSHA512", Hex.decode("9090898971914cb2e65eb1b083f1cad1ce9a9d386f963a2e2ede965fbce0a7121526b5f8aed83f81db60b97ced0bc4b0c27cf23407028cc2f289957f607cec98")); + testPKCS12HMac("HMacRIPEMD160", Hex.decode("cb1d8bdb6aca9e3fa8980d6eb41ab28a7eb2cfd6")); + + try + { + Mac mac = Mac.getInstance("HMacRIPEMD256", "BC"); + + mac.init(new PKCS12Key("hello".toCharArray()), new PBEParameterSpec(new byte[20], 100)); + fail("no exception"); + } + catch (InvalidAlgorithmParameterException e) + { + isTrue("wrong exception", "no PKCS12 mapping for HMAC: RIPEMD256/HMAC".equals(e.getMessage())); + } + + testMixedKeyTypes(); + testNullSalt(); + } + + private void testPKCS12Interop() + throws Exception + { + final String algorithm = "PBEWithSHA256And192BitAES-CBC-BC"; + + final PBEKeySpec keySpec = new PBEKeySpec("foo123".toCharArray(), Hex.decode("01020304050607080910"), 1024); + final SecretKeyFactory fact = SecretKeyFactory.getInstance(algorithm, "BC"); + + BCPBEKey bcpbeKey = (BCPBEKey)fact.generateSecret(keySpec); + + Cipher c1 = Cipher.getInstance(algorithm, "BC"); + + c1.init(Cipher.ENCRYPT_MODE, new PKCS12KeyWithParameters("foo123".toCharArray(), Hex.decode("01020304050607080910"), 1024)); + + Cipher c2 = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); + + c2.init(Cipher.DECRYPT_MODE, new SecretKeySpec(bcpbeKey.getEncoded(), "AES"), new IvParameterSpec(((ParametersWithIV)bcpbeKey.getParam()).getIV())); + + if (!Arrays.areEqual(Hex.decode("deadbeef"), c2.doFinal(c1.doFinal(Hex.decode("deadbeef"))))) + { + fail("new key failed"); + } + + c1.init(Cipher.ENCRYPT_MODE, bcpbeKey); + + if (!Arrays.areEqual(Hex.decode("deadbeef"), c2.doFinal(c1.doFinal(Hex.decode("deadbeef"))))) + { + fail("old key failed"); + } + } + + private void checkPBE(String baseAlg, boolean defIsUTF8, String utf8, String eightBit) + throws Exception + { + byte[] utf8K = Hex.decode(utf8); + byte[] ascK = Hex.decode(eightBit); + + SecretKeyFactory f = SecretKeyFactory.getInstance(baseAlg, "BC"); + KeySpec ks1 = new PBEKeySpec("\u0141\u0142".toCharArray(), new byte[20], 4096, 160); + if (!Arrays.areEqual((defIsUTF8) ? utf8K : ascK, f.generateSecret(ks1).getEncoded())) + { + fail(baseAlg + " wrong PBKDF2 k1 key generated, got : " + new String(Hex.encode(f.generateSecret(ks1).getEncoded()))); + } + + KeySpec ks2 = new PBEKeySpec("\u0041\u0042".toCharArray(), new byte[20], 4096, 160); + if (!Arrays.areEqual(ascK, f.generateSecret(ks2).getEncoded())) + { + fail(baseAlg + " wrong PBKDF2 k2 key generated"); + } + f = SecretKeyFactory.getInstance(baseAlg + "AndUTF8", "BC"); + ks1 = new PBEKeySpec("\u0141\u0142".toCharArray(), new byte[20], 4096, 160); + if (!Arrays.areEqual(utf8K, f.generateSecret(ks1).getEncoded())) + { + fail(baseAlg + " wrong PBKDF2 k1 utf8 key generated"); + } + + ks2 = new PBEKeySpec("\u0041\u0042".toCharArray(), new byte[20], 4096, 160); + if (!Arrays.areEqual(ascK, f.generateSecret(ks2).getEncoded())) + { + fail(baseAlg + " wrong PBKDF2 k2 utf8 key generated"); + } + f = SecretKeyFactory.getInstance(baseAlg + "And8BIT", "BC"); + ks1 = new PBEKeySpec("\u0141\u0142".toCharArray(), new byte[20], 4096, 160); + if (!Arrays.areEqual(ascK, f.generateSecret(ks1).getEncoded())) + { + fail(baseAlg + " wrong PBKDF2 k1 8bit key generated"); + } + + ks2 = new PBEKeySpec("\u0041\u0042".toCharArray(), new byte[20], 4096, 160); + if (!Arrays.areEqual(ascK, f.generateSecret(ks2).getEncoded())) + { + fail(baseAlg + " wrong PBKDF2 k2 8bit key generated"); + } + } + + // for regression testing only - don't try this at home. + public void testMixedKeyTypes() + throws Exception + { + String provider = "BC"; + SecretKeyFactory skf = + SecretKeyFactory.getInstance("PBKDF2WITHHMACSHA1", provider); + // note: the salt would be regarded as too short and the iteration count too small! + PBEKeySpec pbeks = new PBEKeySpec("password".toCharArray(), Strings.toByteArray("salt"), 100, 128); + SecretKey secretKey = skf.generateSecret(pbeks); + PBEParameterSpec paramSpec = new PBEParameterSpec(pbeks.getSalt(), pbeks.getIterationCount()); + + // in this case pbeSpec picked up from internal class representing key + Cipher cipher = + Cipher.getInstance("PBEWITHSHAAND128BITAES-CBC-BC", provider); + + try + { + cipher.init(Cipher.ENCRYPT_MODE, secretKey); + fail("no exception"); + } + catch (InvalidKeyException e) + { + isTrue("wrong exception", "Algorithm requires a PBE key suitable for PKCS12".equals(e.getMessage())); + } + } + + public String getName() + { + return "PBETest"; + } + + + public static void main( + String[] args) + { + Security.addProvider(new BouncyCastleProvider()); + + runTest(new PBETest()); + } +} diff --git a/tls/src/test/java/org/bouncycastle/tls/test/TestAEADNonceGenerator.java b/tls/src/test/java/org/bouncycastle/tls/test/TestAEADNonceGenerator.java index 1b4f805f23..98a28638f4 100644 --- a/tls/src/test/java/org/bouncycastle/tls/test/TestAEADNonceGenerator.java +++ b/tls/src/test/java/org/bouncycastle/tls/test/TestAEADNonceGenerator.java @@ -2,8 +2,7 @@ import org.bouncycastle.tls.crypto.TlsNonceGenerator; import org.bouncycastle.tls.crypto.impl.AEADNonceGenerator; - -import java.util.Arrays; +import org.bouncycastle.util.Arrays; class TestAEADNonceGenerator implements AEADNonceGenerator