diff options
author | David Hook <dgh@cryptoworkshop.com> | 2013-05-12 11:16:33 +0400 |
---|---|---|
committer | David Hook <dgh@cryptoworkshop.com> | 2013-05-12 11:16:33 +0400 |
commit | 70ea15e19d93c86219581f802beff8abd351b4ec (patch) | |
tree | 81ec943df6040951b28ddd273aff45af0f953ff0 | |
parent | bcd5d7192db73ea15afbeb35b00d6d8e2ebed765 (diff) |
added parity bits for DTEA keys
-rw-r--r-- | src/main/java/org/bouncycastle/crypto/prng/drbg/CTRSP800DRBG.java | 21 | ||||
-rw-r--r-- | src/test/java/org/bouncycastle/crypto/prng/test/CTRDRBGTest.java | 65 |
2 files changed, 86 insertions, 0 deletions
diff --git a/src/main/java/org/bouncycastle/crypto/prng/drbg/CTRSP800DRBG.java b/src/main/java/org/bouncycastle/crypto/prng/drbg/CTRSP800DRBG.java index b10d068e..84fe4a40 100644 --- a/src/main/java/org/bouncycastle/crypto/prng/drbg/CTRSP800DRBG.java +++ b/src/main/java/org/bouncycastle/crypto/prng/drbg/CTRSP800DRBG.java @@ -433,6 +433,14 @@ public class CTRSP800DRBG } } + /** + * Pad out a key for TDEA, setting odd parity for each byte. + * + * @param keyMaster + * @param keyOff + * @param tmp + * @param tmpOff + */ private void padKey(byte[] keyMaster, int keyOff, byte[] tmp, int tmpOff) { tmp[tmpOff + 0] = (byte)(keyMaster[keyOff + 0] & 0xfe); @@ -443,5 +451,18 @@ public class CTRSP800DRBG tmp[tmpOff + 5] = (byte)((keyMaster[keyOff + 4] << 3) | ((keyMaster[keyOff + 5] & 0xc0) >>> 5)); tmp[tmpOff + 6] = (byte)((keyMaster[keyOff + 5] << 2) | ((keyMaster[keyOff + 6] & 0x80) >>> 6)); tmp[tmpOff + 7] = (byte)(keyMaster[keyOff + 6] << 1); + + for (int i = tmpOff; i <= tmpOff + 7; i++) + { + int b = tmp[i]; + tmp[i] = (byte)((b & 0xfe) | + ((((b >> 1) ^ + (b >> 2) ^ + (b >> 3) ^ + (b >> 4) ^ + (b >> 5) ^ + (b >> 6) ^ + (b >> 7)) ^ 0x01) & 0x01)); + } } } diff --git a/src/test/java/org/bouncycastle/crypto/prng/test/CTRDRBGTest.java b/src/test/java/org/bouncycastle/crypto/prng/test/CTRDRBGTest.java index 84d672e8..3ff32a4d 100644 --- a/src/test/java/org/bouncycastle/crypto/prng/test/CTRDRBGTest.java +++ b/src/test/java/org/bouncycastle/crypto/prng/test/CTRDRBGTest.java @@ -1,10 +1,16 @@ package org.bouncycastle.crypto.prng.test; +import org.bouncycastle.crypto.BlockCipher; +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.engines.AESEngine; import org.bouncycastle.crypto.engines.AESFastEngine; import org.bouncycastle.crypto.engines.DESedeEngine; +import org.bouncycastle.crypto.params.DESedeParameters; +import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.prng.drbg.CTRSP800DRBG; import org.bouncycastle.crypto.prng.drbg.SP80090DRBG; +import org.bouncycastle.util.Arrays; import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.util.test.SimpleTest; @@ -336,6 +342,15 @@ public class CTRDRBGTest } } + // DESede/TDEA key parity test + DRBGTestVector tv = tests[0]; + + SP80090DRBG drbg = new CTRSP800DRBG(new KeyParityCipher(tv.getCipher()), tv.keySizeInBits(), tv.securityStrength(), tv.entropySource(), tv.personalizationString(), tv.nonce()); + + byte[] output = new byte[tv.expectedValue(0).length]; + + drbg.generate(output, tv.additionalInput(0), tv.predictionResistance()); + // Exception tests SP80090DRBG d; try @@ -447,4 +462,54 @@ public class CTRDRBGTest "D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"), true); } } + + private class KeyParityCipher + implements BlockCipher + { + private BlockCipher cipher; + + KeyParityCipher(BlockCipher cipher) + { + this.cipher = cipher; + } + + public void init(boolean forEncryption, CipherParameters params) + throws IllegalArgumentException + { + byte[] k = Arrays.clone(((KeyParameter)params).getKey()); + + DESedeParameters.setOddParity(k); + + if (!Arrays.areEqual(((KeyParameter)params).getKey(), k)) + { + System.err.println(new String(Hex.encode(((KeyParameter)params).getKey()))); + System.err.println(new String(Hex.encode(k))) ; + fail("key not odd parity"); + } + + cipher.init(forEncryption, params); + } + + public String getAlgorithmName() + { + return cipher.getAlgorithmName(); + } + + public int getBlockSize() + { + return cipher.getBlockSize(); + } + + public int processBlock(byte[] in, int inOff, byte[] out, int outOff) + throws DataLengthException, IllegalStateException + { + return cipher.processBlock(in, inOff, out, outOff); + } + + public void reset() + { + cipher.reset(); + } + } + } |