diff --git a/CONTRIBUTORS.html b/CONTRIBUTORS.html index 6907118b64..875e68bd07 100644 --- a/CONTRIBUTORS.html +++ b/CONTRIBUTORS.html @@ -561,7 +561,8 @@
  • pelzvieh <https://github.com/pelzvieh> fix for CRLs with absent next update in PKIXCRLUtil.
  • Matthias Valvekens <matthias.valvekens@itextpdf.com> new implementation and additional testing for BasicConstraints task in validations package.
  • Bart Bakker <https://github.com/bjpbakker> RFC 5280 boundaries checks for CRLReason and CRLNumber. Addition of binary-signing-time CMS attribute.
  • -
  • Matthias Neugschwandtner and Gergo Barany from Oracle Labs; SICBlockCipher performance optimisation.
  • +
  • Matthias Neugschwandtner and Gergo Barany from Oracle Labs; SICBlockCipher performance optimisation.
  • +
  • Johannes Leupold from KOBIL GmbH; XChaCha20 and XChaCha20Poly1305 initial implementation.
  • diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/XChaCha20Engine.java b/core/src/main/java/org/bouncycastle/crypto/engines/XChaCha20Engine.java new file mode 100644 index 0000000000..ef17447e0a --- /dev/null +++ b/core/src/main/java/org/bouncycastle/crypto/engines/XChaCha20Engine.java @@ -0,0 +1,106 @@ +package org.bouncycastle.crypto.engines; + +import org.bouncycastle.util.Pack; + +/** + * Implementation of eXtended Nonce ChaCha (XChaCha20). + * + * The implementation follows the IETF Draft for XChaCha20-Poly1305 + * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha + * + * XChaCha20 requires a 256bit key and a 192bit IV. + */ +public class XChaCha20Engine extends ChaChaEngine +{ + + /** + * Create a new XChaCha20 engine. + */ + public XChaCha20Engine() + { + super(); + } + + @Override + public String getAlgorithmName() + { + return "XChaCha20"; + } + + @Override + protected int getNonceSize() + { + return 24; + } + + @Override + protected void setKey(byte[] keyBytes, byte[] ivBytes) + { + if (keyBytes == null) + { + throw new IllegalArgumentException( + getAlgorithmName() + " doesn't support re-init with null key"); + } + + if (keyBytes.length != 32) + { + throw new IllegalStateException(getAlgorithmName() + " requires a 256 bit key"); + } + + // Derive sub key using the HChaCha algorithm and set copy it to the engine state + int[] subKey = hChaChaDeriveSubKey(keyBytes, ivBytes); + System.arraycopy(subKey, 0, engineState, 4, subKey.length); + + // Use last 64 bits of input IV as nonce for ChaCha20 + Pack.littleEndianToInt(ivBytes, 16, engineState, 14, 2); + } + + public int[] hChaChaDeriveSubKey(byte[] keyBytes, byte[] ivBytes) + { + if (keyBytes == null) + { + throw new IllegalArgumentException("HChaCha" + rounds + " doesn't support null keys"); + } + + if (keyBytes.length != 32) + { + throw new IllegalStateException("HChaCha" + rounds + " requires a 256 bit key"); + } + + if (ivBytes == null) + { + throw new IllegalArgumentException("HChaCha" + rounds + " needs a non-null IV"); + } + + if (ivBytes.length < 16) + { + throw new IllegalArgumentException( + "HChaCha" + rounds + " needs an at least 128 bit nonce"); + } + + // Set key for HChaCha20 + super.setKey(keyBytes, ivBytes); + Pack.littleEndianToInt(ivBytes, 0, engineState, 12, 4); + + // Process engine state to generate ChaCha20 key + int[] hchacha20Out = new int[engineState.length]; + chachaCore(20, engineState, hchacha20Out); + + // Take first and last 128 bits of output as the sub key + int[] subkey = new int[8]; + System.arraycopy(hchacha20Out, 0, subkey, 0, 4); + System.arraycopy(hchacha20Out, 12, subkey, 4, 4); + + // Remove addition in final round of chachaCore + subkey[0] -= engineState[0]; + subkey[1] -= engineState[1]; + subkey[2] -= engineState[2]; + subkey[3] -= engineState[3]; + subkey[4] -= engineState[12]; + subkey[5] -= engineState[13]; + subkey[6] -= engineState[14]; + subkey[7] -= engineState[15]; + + return subkey; + } +} diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/ChaCha20Poly1305.java b/core/src/main/java/org/bouncycastle/crypto/modes/ChaCha20Poly1305.java index fdcb48bef7..3ac4db41d5 100644 --- a/core/src/main/java/org/bouncycastle/crypto/modes/ChaCha20Poly1305.java +++ b/core/src/main/java/org/bouncycastle/crypto/modes/ChaCha20Poly1305.java @@ -16,7 +16,7 @@ public class ChaCha20Poly1305 implements AEADCipher { - private static final class State + protected static final class State { static final int UNINITIALIZED = 0; static final int ENC_INIT = 1; @@ -41,7 +41,7 @@ private static final class State private final ChaCha7539Engine chacha20; private final Mac poly1305; - private final byte[] key = new byte[KEY_SIZE]; + protected final byte[] key = new byte[KEY_SIZE]; private final byte[] nonce = new byte[NONCE_SIZE]; private final byte[] buf = new byte[BUF_SIZE + MAC_SIZE]; private final byte[] mac = new byte[MAC_SIZE]; @@ -50,7 +50,7 @@ private static final class State private long aadCount; private long dataCount; - private int state = State.UNINITIALIZED; + protected int state = State.UNINITIALIZED; private int bufPos; public ChaCha20Poly1305() diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/XChaCha20Poly1305.java b/core/src/main/java/org/bouncycastle/crypto/modes/XChaCha20Poly1305.java new file mode 100644 index 0000000000..8e114b1916 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/crypto/modes/XChaCha20Poly1305.java @@ -0,0 +1,101 @@ +package org.bouncycastle.crypto.modes; + +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.engines.XChaCha20Engine; +import org.bouncycastle.crypto.params.AEADParameters; +import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.crypto.params.ParametersWithIV; +import org.bouncycastle.util.Pack; + +public class XChaCha20Poly1305 extends ChaCha20Poly1305 implements AEADCipher +{ + private static final int MAC_BYTES = 16; + private static final int KEY_SIZE = 32; + private static final int NONCE_SIZE = 24; + + @Override + public String getAlgorithmName() + { + return "XChaCha20Poly1305"; + } + + @Override + public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException + { + KeyParameter keyParam; + byte[] nonce; + byte[] aad = null; + + if (params instanceof AEADParameters) + { + AEADParameters aeadParams = (AEADParameters) params; + int macSize = aeadParams.getMacSize(); + + if (MAC_BYTES * 8 != macSize) + { + throw new IllegalArgumentException("Invalid value for MAC size: " + macSize); + } + + keyParam = aeadParams.getKey(); + nonce = aeadParams.getNonce(); + aad = aeadParams.getAssociatedText(); + } + else if (params instanceof ParametersWithIV) + { + ParametersWithIV ivParams = (ParametersWithIV) params; + keyParam = (KeyParameter) ivParams.getParameters(); + nonce = ivParams.getIV(); + } + else + { + throw new IllegalArgumentException("invalid parameters passed to XChaCha20Poly1305"); + } + + // Validate nonce + if (nonce == null || NONCE_SIZE != nonce.length) + { + throw new IllegalArgumentException("XChaCha20Poly1305 requires a 192 bit nonce"); + } + + // Validate key + if (null == keyParam) + { + if (State.UNINITIALIZED == state) + { + throw new IllegalArgumentException("Key must be specified in initial init"); + } + + // Derive sub key from old key and new nonce using the HChaCha20 algorithm + XChaCha20Engine xChaCha = new XChaCha20Engine(); + byte[] subKey = Pack.intToLittleEndian(xChaCha.hChaChaDeriveSubKey(key, nonce)); + + keyParam = new KeyParameter(subKey); + } + else + { + if (KEY_SIZE != keyParam.getKey().length) + { + throw new IllegalArgumentException("Key must be 256 bits"); + } + + // Derive sub key using the HChaCha20 algorithm + XChaCha20Engine xChaCha = new XChaCha20Engine(); + byte[] subKey = Pack.intToLittleEndian(xChaCha.hChaChaDeriveSubKey(keyParam.getKey(), + nonce)); + + keyParam = new KeyParameter(subKey); + } + + // Use last 64 bits of nonce prefixed with 4 NUL bytes as nonce for ChaCha20Poly1305 + // Nonce reuse will be caught in super.init(...) + byte[] chaChaNonce = new byte[12]; + System.arraycopy(nonce, 16, chaChaNonce, 4, 8); + + if (aad == null) { + super.init(forEncryption, new ParametersWithIV(keyParam, chaChaNonce)); + } else { + super.init(forEncryption, new AEADParameters(keyParam, + 8 * MAC_BYTES, chaChaNonce, aad)); + } + } +} diff --git a/core/src/test/java/org/bouncycastle/crypto/test/CipherStreamTest.java b/core/src/test/java/org/bouncycastle/crypto/test/CipherStreamTest.java index 48c0d0cfbf..807bcc0077 100644 --- a/core/src/test/java/org/bouncycastle/crypto/test/CipherStreamTest.java +++ b/core/src/test/java/org/bouncycastle/crypto/test/CipherStreamTest.java @@ -32,6 +32,7 @@ import org.bouncycastle.crypto.engines.TEAEngine; import org.bouncycastle.crypto.engines.ThreefishEngine; import org.bouncycastle.crypto.engines.TwofishEngine; +import org.bouncycastle.crypto.engines.XChaCha20Engine; import org.bouncycastle.crypto.engines.XSalsa20Engine; import org.bouncycastle.crypto.engines.XTEAEngine; import org.bouncycastle.crypto.io.CipherInputStream; @@ -508,6 +509,7 @@ private void performTests() testMode(new Salsa20Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8])); testMode(new XSalsa20Engine(), new ParametersWithIV(new KeyParameter(new byte[32]), new byte[24])); testMode(new ChaChaEngine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8])); + testMode(new XChaCha20Engine(), new ParametersWithIV(new KeyParameter(new byte[32]), new byte[24])); testMode(new Grainv1Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8])); testMode(new Grain128Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[12])); testMode(new HC128Engine(), new KeyParameter(new byte[16])); diff --git a/core/src/test/java/org/bouncycastle/crypto/test/RegressionTest.java b/core/src/test/java/org/bouncycastle/crypto/test/RegressionTest.java index d881f4c35b..dbc1718ea4 100644 --- a/core/src/test/java/org/bouncycastle/crypto/test/RegressionTest.java +++ b/core/src/test/java/org/bouncycastle/crypto/test/RegressionTest.java @@ -109,6 +109,8 @@ public class RegressionTest new XSalsa20Test(), new ChaChaTest(), new ChaCha20Poly1305Test(), + new XChaCha20Test(), + new XChaCha20Poly1305Test(), new CMacTest(), new EAXTest(), new GCMTest(), diff --git a/core/src/test/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java b/core/src/test/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java index 092de5fb66..dbac317f2f 100644 --- a/core/src/test/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java +++ b/core/src/test/java/org/bouncycastle/crypto/test/StreamCipherResetTest.java @@ -13,6 +13,7 @@ import org.bouncycastle.crypto.engines.ISAACEngine; import org.bouncycastle.crypto.engines.RC4Engine; import org.bouncycastle.crypto.engines.Salsa20Engine; +import org.bouncycastle.crypto.engines.XChaCha20Engine; import org.bouncycastle.crypto.engines.XSalsa20Engine; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; @@ -42,6 +43,7 @@ public void performTest() random(24))); testReset(new ChaChaEngine(), new ChaChaEngine(), new ParametersWithIV(new KeyParameter(random(32)), random(8))); testReset(new ChaChaEngine(), new ChaChaEngine(), new ParametersWithIV(new KeyParameter(random(16)), random(8))); + testReset(new XChaCha20Engine(), new XChaCha20Engine(), new ParametersWithIV(new KeyParameter(random(32)), random(24))); testReset(new RC4Engine(), new RC4Engine(), new KeyParameter(random(16))); testReset(new ISAACEngine(), new ISAACEngine(), new KeyParameter(random(16))); testReset(new HC128Engine(), new HC128Engine(), new ParametersWithIV(new KeyParameter(random(16)), random(16))); diff --git a/core/src/test/java/org/bouncycastle/crypto/test/XChaCha20Poly1305Test.java b/core/src/test/java/org/bouncycastle/crypto/test/XChaCha20Poly1305Test.java new file mode 100644 index 0000000000..07d5ec4e07 --- /dev/null +++ b/core/src/test/java/org/bouncycastle/crypto/test/XChaCha20Poly1305Test.java @@ -0,0 +1,236 @@ +package org.bouncycastle.crypto.test; + +import org.bouncycastle.crypto.modes.XChaCha20Poly1305; +import org.bouncycastle.crypto.params.AEADParameters; +import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.crypto.params.ParametersWithIV; +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.encoders.Hex; +import org.bouncycastle.util.test.SimpleTest; + +public class XChaCha20Poly1305Test extends SimpleTest +{ + + private static class TestCase + { + + private final byte[] key; + private final byte[] iv; + private final byte[] plaintext; + private final byte[] aad; + private final byte[] taggedCiphertext; + + public TestCase(String key, String iv, String plaintext, String aad, + String taggedCiphertext) + { + this.key = Hex.decode(key); + this.iv = Hex.decode(iv); + this.plaintext = Hex.decode(plaintext); + this.aad = Hex.decode(aad); + this.taggedCiphertext = Hex.decode(taggedCiphertext); + } + + public byte[] getKey() + { + return key; + } + + public byte[] getIv() + { + return iv; + } + + public byte[] getPlaintext() + { + return plaintext; + } + + public byte[] getAad() + { + return aad; + } + + public byte[] getTaggedCiphertext() + { + return taggedCiphertext; + } + } + + // Test cases randomly generated by libsodium + private static final TestCase[] TEST_CASES = new TestCase[]{ + new TestCase("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "404142434445464748494a4b4c4d4e4f5051525354555657", + "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e", + "50515253c0c1c2c3c4c5c6c7", + "bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b4522f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff921f9664c97637da9768812f615c68b13b52ec0875924c1c7987947deafd8780acf49"), + new TestCase("091b328d56f9e584d771a7d94b541ffd365c1f421f708574eb958db12337555f", + "aaf932005aea94e1ba42fdb878047254cfce60a36e6cac84", + "388109916fce12994316221ae27ef74d3a0bcda727fedad6a8ea2192d16f624fdbbd051de74ac1db74", + "0b7e9b1170fd59bd678e87f9404a1ca143ac1a9f1432e6d16fe789ff66bced6f7c3d351d270ea2a5892fa4f315f67bcfe1b7cb76b805", + "46e9c8995c53d3a345230a830272bace62b16808fecc1e4ef7d75aeb7d05049aeb0be6db05f0f1da34e9b912a380430946def04001b5fe5ba1"), + new TestCase("939419b46630b7438ff85f6e77b6b7451e2a3888f8631710f6259c700c7431ee", + "98a1dfdda1745e6359b02c0afb69cb3b2688fbd57cdc9585", + "7414f45787de1935d39c7529c195d5cba7a7b1cded510e32a3bcd2cfc6a1a4cfe89032eff7ee5437f9f277c5ad4583df271c6a8363", + "d235b8a07532d5f127d707f4630bd2ce23bafb82eb8f07baa9e7e8b513b3f6edfeee1aed11132709", + "dda44e5f0758746dc84d00c8e62128a2ed98baab377c888481e23a163f1cfcb604f627eb5d4c5f0041c8b86972ad3f6c1cacea6f159c784642a00738be24aecd98142b3131"), + new TestCase("53862f0a4b8df9c19c0b58672f5a20c2516a86c24f0ec80062896db2bcffc784", + "35cf7c63727c472a42b4295923e5dca7b1f00a1b5fd766d8", + "5e62527ee8f16833fc11c243317b88f2d3323757ca394c4436df112192c96645c6388edeebb6c7a9d7966cd5fae64b8a49c2d754ffa02b6f9793f356f84459fbc8ef4bac7327eedf6bc602fb336dea", + "dabb6b51c02278273dbb4baae238ec5f", + "2c6671d3c176d864fc2ee72101b73bfb7d74f4ea948d0a61392634756fe4a25402ca96d70139cdebb5c90f5bedde3d406033ca15f8a37944dd2a9c51da8841e52116675df49acd3d89a1a00ec386270fd41fa03728be476aa74829b373f0f9"), + new TestCase("88eb83d5290886e29df44b16133fe81d6086945ef77b487449ba97eede2ec96a", + "040c9392d2806e60579348b025c3450f98f895fcd397a4b3", + "881fc800cc55cf02699394db3de2440b47bee8208d9873b3dc1b5c5417b3a5998d649f16838cc5a1912fed46a7d20dc2a58dd1c69a7ad85d50ab485c8756473b94cc2439936a1d05e2acd69fbd19b915695bdd7f298821b1eb139e", + "87", + "19064dd3a9a26b01549d7e7be47f393d7b1d9cb1180726e788b096df7e30d8e940d1308a90849b98a8a02e6117a89c59681169b0c96cdeabda081b0ddcf20003f17f0bd9cb416a5c3d0ba6287c214854a63de6aa82c17a037e2aaf96a05fb55b64457be615260a04f65f43"), + new TestCase("736353a6798e0fffaef2ceeb4e2cc12173156f8c9504c76ec0b4352ef0222003", + "6d481374ff1d92f0bae325ff8166903052b61babd6f65567", + "20a4eec9376e7bf3ed8f52152707bf0ef214794fb759df6416fcd42d5dc441abb6428d11399cca54c0e861b2684e0e24d3d81b9f4f396e697483218e6dcbdb8960543e504eb9682acf2200808ddc74462c325f8ebf11c125640060682e5f84b886f5660e1f026b588c964a492e94cf", + "69", + "5ec5f66b3e72ffc476f2c1a570ad76592baf1b341076720e65cde18859d40caaae388ff27bb735b9b83ff8a8a32892a556292fd11e3eaba606df5aff518e0a3885a3e89781d2a5c58e7d3246b5e4cbf48bd59a7559866bda69bc48a785d6dee8daa1d107e08f90b4168495e0d93a5dec8436bb36d3b90e8ce1720d80c06ff5"), + new TestCase("b85acb3d38e58e3e0e5c18d0b3a90aa53cee466e17d0c997c5ffeea0324c5e13", + "de33f235b18392ba2666eba717f4f774a8b8d186129a6b8e", + "aee6c6db6578b7e48fa1a7f142441d95ddd0bf690223563e5917d097623ec1c518a6668101c2ca8a3f909adf0aaa78d72178694e7799f6a1d37543b56aabd3c445507e612b4aa6b1a390031101070264abeb09e486a4252836e464c1a26e", + "cd9bb15dbf6fbc676731b011b5cc92874051682f38acdc8b91bf27b3793b25341556bf67d56e6f", + "c52c2ca2652c9783503e60f9c3c3cf737a8dedf791675dd76fa85991ecfa42953b94c566affd264de6ef29a9cffa51a9a7dcd0469c307289baad3a78fd5192113b63efd93ad012ec6bb05b935ab34f0ebe994e06575665dc2f64c8e8f6ac209458ffdbc48e6915b28fe950c619fb"), + new TestCase("2a9b873f6faf3992c05d531aaaae873353d4da31067f2497e3ab8fc337d4c0fd", + "859beebf5d6aff8c37a9c850478731f33b455c0f168f852c", + "13452a24bcc354428b0c31d9a58f7239cc344066be588b044207395a62cbaadd43f8689e9704fd80f7f2b47b9754676b2ee3a6e38f3f38d875efcf9366407649e4b3018bc68865e815ea74e42d4e", + "ede91d919d6db87b2ba16cc301c01f3057919b82a704b873f5979fabc72c4b", + "d82a9b49d0216048d1310aed0cb1225a0291e3368d01b1be5098b7974520a85841288246dc5a58d75b16f81ca201bc297e4705fea2360cc706b52db68356528390da7c3c677923d77061731fb92a52564df01a41ed93a8f02ea85d5be1c6"), + new TestCase("17317a9b895fa885b302b895abc5e382943aaaa37b06a9e5dc1fcf7e8eb5392b", + "0f86aeeea6d8e81e2cac7a6123f239458b8f6fe4d3f5ed36", + "c7dd7f40ea288564b06b07e2db953256eb37131d7f6439e53e3115025fc5d4cb3da26b72c86d9e09ad78", + "fb9cb095f4a2db", + "20a849f5ca136773d55db982d7ae09c630d65dae6ce5924c01c96a8a6ba1e6c89d94cbdb7db0f9d9f5fd7ef488d8a2ae165a5411b6aa5b741580"), + new TestCase("7239d52dde582ee478c2d9f4356862fc852cbb91f9f6f4c02e5deeff12e45da4", + "94366355a5bac385d0ceff6ef4faa0ab163afc6d2bed91d5", "eb5c7cf0cb84a67a2bf3cbfd", + "371a661b485bef33abe4387a2eb7f33b62795773d6c326da666f9634b6120fcab82a766c52f84961d40bb548e5fc610b7b8f0c0dea95", + "c36bccc6823f7f688b245436d8943ef58a2ad2d877cf47a919420f88"), + new TestCase("460a7e604d2cb558be74e95bd2ed3e835d46a77c4e531de32f1946f7d50841a2", + "82b9f1c0838ee20c1816762c480e09e474ff87af9a015891", + "460400404d2838ab8d1db3dfedb0fb538635860c189b1cfba0da467da12c3f6137d3e7146fb00c62a11bce45c8bcfca57edff18661ac5feedf8b", + "8135e6cb133b3edaf94902f0c124", + "9365bd370c047f8313aebf34e0bf3359f7dee954ce542cff3bb8c0c0e18122295a772cc7d7703bdd4433ba3839d46671d3338146db12c0f121d45ce2296c6b96800a2692deed16997f9d"), + new TestCase("5793f3fc2dfe3539ba27528a1dbf483203e9c911c102b90118ef46e43797bbd8", + "db5afb8672ab9041decb0e4fa70e91e7a77ad50f44f2f941", + "9309c9855594e0019e8b052759539a7ba7297f984deba5422ec6da66c8d06647b92bcbadc15d8077c8d580373d9c9f3511a668711641c5d2e80161f533d9ccb3e21f691b37a9bb6b73016256d949e72a02a212b069827a502624288d7cfd", + "a5a59b8186412b6f", + "583a07049f8f7c53da94c290fd208f4168a04e8dbf750ff658e93c4eab3287df5e91f866df19312ca23d2c83e5768fdb25adec860e30ec0448e00fd090b29a2606d005e632a93e50418de9b98458ee0b62106bfaaca44b6ef88a0ab7b46bfe182c8249592815a17c324d5cadcd24"), + new TestCase("ebb6fd81106ce21d1ab0a7f7a27151d928661361669f3046cefbeaa2aced3617", + "9b881299dbb29c0117784f91cf04b710f3b578c02bd87346", + "169cd1f3e17e3bf3bc5c5451abdd42be29b20760", + "8277aa1b7784ae88432108b251730ac4dca4d1d90eb42e15ef368377826bc56d28d92dbc45912de607eaa7142bb899ae0f", + "68bfc9aa111d12d2c05e2c9e0571b859f47ddba6cad0411334f4cdfcbc5fd6d4be64513d"), + new TestCase("2c82b36af3c5a8124032890ec818a00a04c023570d51500e621b368b346b5eb6", + "e4f6658c95318e4712103ec174be202388b5f1e65bd487d0", "d62a0037876e", + "d1a19c0d6c333fbc15cb9457caf04583873531bd241b49e79865", + "3e15f9336af6626206dd6464b60f247b0527296982d3"), + new TestCase("800881c00c9d03330db3d6713a68638d1e0224742401125d351123549d4bdb52", + "b20e77b4869022a5947c9d8ecbceb8b21d664ef1b33890bd", + "f68e14b8461287245e8e89e35197316a8ac047e8e6932ba11c923bf530b6320d4c18bd53526a09cd98ce700ae3ce378fc5a6d77afadab93d64346da88fdeedd4942ea4b97beae782a1a3f671aef5634545c6a9b1b91908cb0346679cd1fc", + "bad2ade2460f7a7be05e82225e3701", + "8b814e5a5b92537fa7998852670588c47b15b3100f0742b1d06c20def5ae9555e4a59f02c10e985e34b41a2adbce6e9f0c1f02f62b7519147278d524151d1ab06cef5c6b6d6371bf939cfdd6c57b0e646ac95635790b03d875272ddcfa9c0cccaf46619c7f63d33abeefba33f03f"), + new TestCase("e14cc36b2e4657128e462a73aea25a5b15d5ec8917faf415bc0580ac7cfd0e5f", + "3c212f13e8d26f6719f3c5a6ea414330994582fd14e989ef", + "650fa8359a5c2e83b6685e1db9d9124b85f7ecdba61935e6b5ed2fb8", + "fd0df3d8aa5fc24265107e7621301f781fcebdd21c1c8d696bbe3d18055f5d66827a53e4e79ce0e5495a64668a8718b82d4d6ce78c5da20d", + "09c88d4dc277ba69fb2b043a08dc73a8f248966aab2ebe889e0e222c31932de593821781481144bf4f47dcd1"), + new TestCase("17e4febc9a229c3d98848090aa0f7d14fc654867b093de0555557168b16f1a51", + "1cddef425b48d7f9cfe1798f7f035d74cd0f6831421a9e4d", + "163c4dc339a3d29858f27bb5798f7020e4388fb17eadd64a65b7998ee37583adbd02e805264fdb0d4e17e343140656bc6a23ec8ccf0dbfddb7cf0f7221fe486a8c448eed5c7141", + "05478f4551b2f5cd63ca6a712deb89a5e301e3937b7a6503038fbf970327930d", + "82871babefc82d27f471a13b5b553aef343c89795c2083d6b3b675c9ecaf6d374d9f9e7707af40538fdedb2f7a5af116531672909f3e03da6df8377a1afa8bf499071972924b2426f08aa06273b41650886815329e246d"), + new TestCase("d044beed1512d77ae932392a7d7b74784596ddd9a395c04bfa3e51e8ea3ddae8", + "cbaef78c420218e4e1c98c136887438165f0b9631899bbaa", + "f4eb98202bc6fb5b5372a4383e07352f46de5917b43b596941a18847b3cd03eda19092df247c46b445d82ef3a6a2d7e7c0db5e5198287467468962ace5ad063e17e5d6c219f8ed7b6ce6c753297838c04a5934b9fdc0c9fe0b4dca55b8ef12c0", + "9eda9ea7fa8326cb80aecd6315afe1956b20ee7e60a0b7e58b19fc9ad780acfa8e40a58cf10abcc251ed4a1a226b6e509ea046664a295d3ae4aeffb1", + "09da30408007de1e2caca06c9163eaf6d441c1d4689a6785e3b6426d1368f7b655b2b9663ba7d4f43977db13362ad4ff008e46c5898d4c57977926f7aa9d548dc62e25707fb2e59525ea415449c02ee296843612c81cbad168f088d35d2ebba1dc0bf90dcdd84bf93a663e3a2170fc81"), + new TestCase("162626067ca61f0393928af9e6931aefbdda54a1776ead5388a718977a6cc230", + "37c2d5a0230a1e94cec73542d0a07ff9a199f3f67f2c86e0", + "4625513a4059074c037a48d6c033443523b072ec162900bbce9d139a33f2d33342", + "1a02044fb636daf5925469", + "1d3d0f5c760c6ea07282013f853c2db538ce564b771ee694308533270e32dc88b31472eef1fea4317156766560ccb5cda6"), + new TestCase("07762246957741daf0486afeeb01746d2706a572157f792738de03b127a02016", + "a5af745018ea8f266001d22e1b2d06f428f5b82c47b853e3", + "ee19ed61b1f835aa29df1ee3f1bf6a3bfc62b6580f8b7f3a1297f9b749175035f7abfe8a", + "3e8f81dee69f3c7b9d313a7f151fdc59c4fee24ccba406505c3afd3e804058dfe89df90bec4fcda8c091f0df2b5def6ee865e84d232e66", + "3bbc711e971bf20b104ced62afa5bd65904b49d88f058c6e2724eea7c2816b7e939638861386187e4b07491ed869e32878a25b80"), + new TestCase("23e7c19d5ba541b146b1403f4c1ea990e3aae837f560d912fed87f36e86bc91b", + "37e5c442f179962d5635701e2b7e2119def2d1ba334f091d", + "701c8d39922b41f324c7234fd14722622d22a0333a68fd53e6d12cf5136081d93076cf38", + "bb8540c33d6297c538a68191571ff01189c65aa023c0c01628c6f0514eb541c0b3ffa387e0ca0f6949f67b15ead3ffff13988a668e06", + "8aa7637d0c67331f4827c68e2761df01897338d9230e1c810f4c8a58fc2feaa2f8e3fa1d7fe4c70c90835a337425392d8ef4b1f0"), + new TestCase("80c64b636fcf5ebb749a3654617091c75b924c8f4efbce749f9ba92c8e0f4967", + "61dd9bab5da491d3897cd19724db3f10ed5d7104e91651d4", "7831f7f9e11453495b2dd4856558f8", + "1e6224186bc830efd07026de94f13a3548668a381da5", + "a9df1f44741b1748bbfa5024dc2383c2eee3a1f2a10ab504f8959c5c618c63"), + new TestCase("1982a592e961177e030c91fcbabf24439781bd09f8a8f73916623934abcfe68f", + "5121b03c73d6f72ca0e41bd1e3d8bfb99299ca9da661a037", + "38ecaf8b2e5969a2ff9e2818c958b57f0f5b48bf23683d75a0db4a4629d3e50a401acb6888d847c4af7bf4aac5ccd62322f89efb8640358c231e60be70fb03eedaf2a50212f73018e8ab7c272ceade6ab680e3c6d5d5fd6a", + "647e6df6bd6c8f0b1dbd8ccdf6d111b6717fe7e326b8828722c9ee60f68cd82c3cdab55e", + "07efc05ecf39ba05a90e79516835f616f8652c5c97be57ab0dde00e7fc09a61b147022e52bd7edf5c449d1c4c660a64567d6bf60a16b8c2bbc0903a12f123e0f1413f1639ac263af9a131564c2002556f2a80789a0938ab29bd425205531eb91e97331684bdbd4fb"), + new TestCase("3366f519d59a1026f093ee3d86a383122788c0df802683d14f40ae023675fee7", + "89550e2dd20279a757e7404c1066be40b911ff93e847a9ac", + "8190be50d139e6bcc360915fe4cc55d85041932b2c0aad6289a777fc4078570b593eb9ed62f7446e7de42e7288ee14", + "7527503480d49cd130e1eb4a3347117b34f8861bc783f2da8d1b4aa5a38fa1610b33d159dc4a32d267b04ff2ed63706b2a49fc49", + "bc6a4997059558f5ccc4da172511d89f2eb7d926cf8877db8321a5fd895d11a4703c3c99fce5b51ff3474a741a9b95c01c49d77dd8e888899a9da4baab7821"), + new TestCase("1f35251df0afa90cfdb4d3257c044bf9300b33522a8aeedcdd0d8503d9934792", + "27776c7292ecb70ccf0a762be7b8c4955507179263266c57", + "571784fa3349d596df520a18eddae351c24b37f1fe2a87a58d0a43734ee327decf4c9e65bfbf959fc67d9145d4160c2d42c34eeb58b438321ada2082fec9be0d71949182f8f4bcf0d75eba4d6ee096", + "37bc72a94b2744e276e21c38024618887c2109f3878ca44581d7623ce08bbc89081a0811", + "c639ba4e5e4b9a7449fa8e36589b17bcb265d544d9a151272fb090fa66b0263295c5838ad7cc440cb7bed2f2e1934a6d39e0cc95dc9f7b73531174ed8e317348ca216bd4460b69782e5c02ff842317877226b96007a05a44fcfe4bd509222b"), + new TestCase("0f23ad99e9187b63de26370115cdd1aa45e2302b142e6fbbfe60e7983450387b", + "da7eec62fda818af0ee5f88e34266be4eab19e47e9e74d90", "790a", + "94c21e447eb200d3595458280c78feaa1cd4df34bba81cb3a8e143a547c1a7b5", + "ed916bc45038c18e5f25419f80da4c8d26fe"), + }; + + public String getName() + { + return "XChaCha20Poly1305"; + } + + public void performTest() throws Exception + { + for (int i = 0; i < TEST_CASES.length; i++) + { + performTest(i, TEST_CASES[i]); + } + } + + private void performTest(int number, TestCase testCase) throws Exception + { + final byte[] plaintext = testCase.getPlaintext(); + + XChaCha20Poly1305 engine = new XChaCha20Poly1305(); + + if (testCase.aad.length > 0) + { + engine.init(true, + new AEADParameters(new KeyParameter(testCase.getKey()), 128, testCase.getIv(), + testCase.getAad())); + } + else + { + engine.init(true, + new ParametersWithIV(new KeyParameter(testCase.getKey()), testCase.getIv())); + } + + byte[] output = new byte[engine.getOutputSize(plaintext.length)]; + int outputBytes = engine.processBytes(testCase.getPlaintext(), 0, + testCase.getPlaintext().length, output, 0); + engine.doFinal(output, outputBytes); + + if (!Arrays.areEqual(testCase.getTaggedCiphertext(), output)) + { + fail("mismatch on " + number, new String(Hex.encode(testCase.getTaggedCiphertext())), + new String(Hex.encode(output))); + } + } + + public static void main(String[] args) + { + runTest(new XChaCha20Poly1305Test()); + } +} diff --git a/core/src/test/java/org/bouncycastle/crypto/test/XChaCha20Test.java b/core/src/test/java/org/bouncycastle/crypto/test/XChaCha20Test.java new file mode 100644 index 0000000000..f46038e9ba --- /dev/null +++ b/core/src/test/java/org/bouncycastle/crypto/test/XChaCha20Test.java @@ -0,0 +1,125 @@ +package org.bouncycastle.crypto.test; + +import org.bouncycastle.crypto.engines.XChaCha20Engine; +import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.crypto.params.ParametersWithIV; +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.encoders.Hex; +import org.bouncycastle.util.test.SimpleTest; + +public class XChaCha20Test extends SimpleTest +{ + + private static class TestCase + { + + private final byte[] key; + private final byte[] iv; + private final byte[] plaintext; + private final byte[] ciphertext; + + public TestCase(String key, String iv, String ciphertext) + { + this(key, iv, Hex.toHexString(new byte[ciphertext.length() / 2]), ciphertext); + } + + public TestCase(String key, String iv, String plaintext, String ciphertext) + { + this.key = Hex.decode(key); + this.iv = Hex.decode(iv); + this.plaintext = Hex.decode(plaintext); + this.ciphertext = Hex.decode(ciphertext); + } + + public byte[] getKey() + { + return key; + } + + public byte[] getIv() + { + return iv; + } + + public byte[] getPlaintext() + { + return plaintext; + } + + public byte[] getCiphertext() + { + return ciphertext; + } + } + + // Test cases from libsodium + // https//raw.githubusercontent.com/jedisct1/libsodium/master/test/default/xchacha20.c + private static final TestCase[] TEST_CASES = new TestCase[]{ + new TestCase("79c99798ac67300bbb2704c95c341e3245f3dcb21761b98e52ff45b24f304fc4", + "b33ffd3096479bcfbc9aee49417688a0a2554f8d95389419", + "c6e9758160083ac604ef90e712ce6e75d7797590744e0cf060f013739c"), + new TestCase("ddf7784fee099612c40700862189d0397fcc4cc4b3cc02b5456b3a97d1186173", + "a9a04491e7bf00c3ca91ac7c2d38a777d88993a7047dfcc4", + "2f289d371f6f0abc3cb60d11d9b7b29adf6bc5ad843e8493e928448d"), + new TestCase("3d12800e7b014e88d68a73f0a95b04b435719936feba60473f02a9e61ae60682", + "56bed2599eac99fb27ebf4ffcb770a64772dec4d5849ea2d", + "a2c3c1406f33c054a92760a8e0666b84f84fa3a618f0"), + new TestCase("5f5763ff9a30c95da5c9f2a8dfd7cc6efd9dfb431812c075aa3e4f32e04f53e4", + "a5fa890efa3b9a034d377926ce0e08ee6d7faccaee41b771", + "8a1a5ba898bdbcff602b1036e469a18a5e45789d0e8d9837d81a2388a52b0b6a0f51891528f424c4a7f492a8dd7bce8bac19fbdbe1fb379ac0"), + new TestCase("eadc0e27f77113b5241f8ca9d6f9a5e7f09eee68d8a5cf30700563bf01060b4e", + "a171a4ef3fde7c4794c5b86170dc5a099b478f1b852f7b64", + "23839f61795c3cdbcee2c749a92543baeeea3cbb721402aa42e6cae140447575f2916c5d71108e3b13357eaf86f060cb"), + new TestCase("91319c9545c7c804ba6b712e22294c386fe31c4ff3d278827637b959d3dbaab2", + "410e854b2a911f174aaf1a56540fc3855851f41c65967a4e", + "cbe7d24177119b7fdfa8b06ee04dade4256ba7d35ffda6b89f014e479faef6"), + new TestCase("6a6d3f412fc86c4450fc31f89f64ed46baa3256ffcf8616e8c23a06c422842b6", + "6b7773fce3c2546a5db4829f53a9165f41b08faae2fb72d5", + "8b23e35b3cdd5f3f75525fc37960ec2b68918e8c046d8a832b9838f1546be662e54feb1203e2"), + new TestCase("d45e56368ebc7ba9be7c55cfd2da0feb633c1d86cab67cd5627514fd20c2b391", + "fd37da2db31e0c738754463edadc7dafb0833bd45da497fc", + "47950efa8217e3dec437454bd6b6a80a287e2570f0a48b3fa1ea3eb868be3d486f6516606d85e5643becc473b370871ab9ef8e2a728f73b92bd98e6e26ea7c8ff96ec5a9e8de95e1eee9300c"), + new TestCase("aface41a64a9a40cbc604d42bd363523bd762eb717f3e08fe2e0b4611eb4dcf3", + "6906e0383b895ab9f1cf3803f42f27c79ad47b681c552c63", + "a5fa7c0190792ee17675d52ad7570f1fb0892239c76d6e802c26b5b3544d13151e67513b8aaa1ac5af2d7fd0d5e4216964324838"), + new TestCase("9d23bd4149cb979ccf3c5c94dd217e9808cb0e50cd0f67812235eaaf601d6232", + "c047548266b7c370d33566a2425cbf30d82d1eaf5294109e", + "a21209096594de8c5667b1d13ad93f744106d054df210e4782cd396fec692d3515a20bf351eec011a92c367888bc464c32f0807acd6c203a247e0db854148468e9f96bee4cf718d68d5f637cbd5a376457788e6fae90fc31097cfc"), + }; + + public String getName() + { + return "XChaCha20"; + } + + public void performTest() throws Exception + { + for (int i = 0; i < TEST_CASES.length; i++) + { + performTest(i, TEST_CASES[i]); + } + } + + private void performTest(int number, TestCase testCase) + { + final byte[] plaintext = testCase.getPlaintext(); + byte[] output = new byte[plaintext.length]; + + XChaCha20Engine engine = new XChaCha20Engine(); + engine.init(true, + new ParametersWithIV(new KeyParameter(testCase.getKey()), testCase.getIv())); + + engine.processBytes(testCase.getPlaintext(), 0, testCase.getPlaintext().length, output, 0); + + if (!Arrays.areEqual(testCase.getCiphertext(), output)) + { + fail("mismatch on " + number, new String(Hex.encode(testCase.getCiphertext())), + new String(Hex.encode(output))); + } + } + + public static void main(String[] args) + { + runTest(new XChaCha20Test()); + } +} diff --git a/core/src/test/jdk1.1/org/bouncycastle/crypto/test/RegressionTest.java b/core/src/test/jdk1.1/org/bouncycastle/crypto/test/RegressionTest.java index 5e1eb4a4ba..78cbfa5f38 100644 --- a/core/src/test/jdk1.1/org/bouncycastle/crypto/test/RegressionTest.java +++ b/core/src/test/jdk1.1/org/bouncycastle/crypto/test/RegressionTest.java @@ -100,6 +100,7 @@ public class RegressionTest new Salsa20Test(), new XSalsa20Test(), new ChaChaTest(), + new XChaCha20Test(), new CMacTest(), new EAXTest(), new GCMTest(), diff --git a/core/src/test/jdk1.2/org/bouncycastle/crypto/test/RegressionTest.java b/core/src/test/jdk1.2/org/bouncycastle/crypto/test/RegressionTest.java index 3206b58d33..5f2ad2b16a 100644 --- a/core/src/test/jdk1.2/org/bouncycastle/crypto/test/RegressionTest.java +++ b/core/src/test/jdk1.2/org/bouncycastle/crypto/test/RegressionTest.java @@ -100,6 +100,7 @@ public class RegressionTest new Salsa20Test(), new XSalsa20Test(), new ChaChaTest(), + new XChaCha20Test(), new CMacTest(), new EAXTest(), new GCMTest(), diff --git a/core/src/test/jdk1.4/org/bouncycastle/crypto/test/RegressionTest.java b/core/src/test/jdk1.4/org/bouncycastle/crypto/test/RegressionTest.java index 3206b58d33..5f2ad2b16a 100644 --- a/core/src/test/jdk1.4/org/bouncycastle/crypto/test/RegressionTest.java +++ b/core/src/test/jdk1.4/org/bouncycastle/crypto/test/RegressionTest.java @@ -100,6 +100,7 @@ public class RegressionTest new Salsa20Test(), new XSalsa20Test(), new ChaChaTest(), + new XChaCha20Test(), new CMacTest(), new EAXTest(), new GCMTest(), diff --git a/docs/specifications.html b/docs/specifications.html index 3e1d2bb816..092712df9f 100644 --- a/docs/specifications.html +++ b/docs/specifications.html @@ -178,6 +178,7 @@

    Symmetric (Block)

    KCCMBlockCipherBlockCipherDSTU 7624 Packet mode - requires all data up front. OCBBlockCipherBlockCipher  ChaCha20Poly1305AEADCipher  +XChaCha20Poly1305AEADCipher 

    @@ -264,6 +265,7 @@

    Symmetric (Stream)

    HC128Engine128  HC256Engine256  ChaChaEngine128/25664 bit IV +XChaCha20Engine256192 bit IV Salsa20Engine128/25664 bit IV XSalsa20Engine256192 bit IV ISAACEngine32 .. 8192  @@ -663,8 +665,9 @@

    Symmetric (Stream)

    HC128(128)  HC256(256)  ChaCha128/25664 bit IV +XChaCha20256192 bit IV Salsa20128/25664 bit IV -XSalsa20256182 bit IV +XSalsa20256192 bit IV VMPC128/6144(128)  Grainv18064 bit IV Grain12812896 bit IV diff --git a/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/XChaCha20.java b/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/XChaCha20.java new file mode 100644 index 0000000000..b13f6ff37c --- /dev/null +++ b/prov/src/main/java/org/bouncycastle/jcajce/provider/symmetric/XChaCha20.java @@ -0,0 +1,90 @@ +package org.bouncycastle.jcajce.provider.symmetric; + +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.crypto.CipherKeyGenerator; +import org.bouncycastle.crypto.engines.ChaCha7539Engine; +import org.bouncycastle.crypto.engines.ChaChaEngine; +import org.bouncycastle.crypto.engines.XChaCha20Engine; +import org.bouncycastle.crypto.modes.ChaCha20Poly1305; +import org.bouncycastle.crypto.modes.XChaCha20Poly1305; +import org.bouncycastle.jcajce.provider.config.ConfigurableProvider; +import org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher; +import org.bouncycastle.jcajce.provider.symmetric.util.BaseKeyGenerator; +import org.bouncycastle.jcajce.provider.symmetric.util.BaseStreamCipher; +import org.bouncycastle.jcajce.provider.symmetric.util.IvAlgorithmParameters; +import org.bouncycastle.jcajce.provider.util.AlgorithmProvider; + +public final class XChaCha20 +{ + private XChaCha20() + { + } + + public static class Base + extends BaseStreamCipher + { + public Base() + { + super(new XChaCha20Engine(), 24); + } + } + + public static class KeyGen + extends BaseKeyGenerator + { + public KeyGen() + { + super("XChaCha20", 256, new CipherKeyGenerator()); + } + } + + public static class BaseXCC20P1305 + extends BaseBlockCipher + { + public BaseXCC20P1305() + { + super(new XChaCha20Poly1305(), true, 24); + } + } + + public static class AlgParams + extends IvAlgorithmParameters + { + protected String engineToString() + { + return "XChaCha20 IV"; + } + } + + public static class AlgParamsXCC1305 + extends IvAlgorithmParameters + { + protected String engineToString() + { + return "XChaCha20-Poly1305 IV"; + } + } + + public static class Mappings + extends AlgorithmProvider + { + private static final String PREFIX = XChaCha20.class.getName(); + + public Mappings() + { + } + + public void configure(ConfigurableProvider provider) + { + + provider.addAlgorithm("Cipher.XCHACHA20", PREFIX + "$Base"); + provider.addAlgorithm("KeyGenerator.XCHACHA20", PREFIX + "$KeyGen"); + provider.addAlgorithm("AlgorithmParameters.XCHACHA20", PREFIX + "$AlgParams"); + + provider.addAlgorithm("Alg.Alias.KeyGenerator.XCHACHA20-POLY1305", "XCHACHA20"); + + provider.addAlgorithm("Cipher.XCHACHA20-POLY1305", PREFIX + "$BaseXCC20P1305"); + provider.addAlgorithm("AlgorithmParameters.XCHACHA20-POLY1305", PREFIX + "$AlgParamsXCC1305"); + } + } +} diff --git a/prov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java b/prov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java index f2798711b2..a6373e52a6 100644 --- a/prov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java +++ b/prov/src/main/java/org/bouncycastle/jce/provider/BouncyCastleProvider.java @@ -88,7 +88,7 @@ public final class BouncyCastleProvider extends Provider "AES", "ARC4", "ARIA", "Blowfish", "Camellia", "CAST5", "CAST6", "ChaCha", "DES", "DESede", "GOST28147", "Grainv1", "Grain128", "HC128", "HC256", "IDEA", "Noekeon", "RC2", "RC5", "RC6", "Rijndael", "Salsa20", "SEED", "Serpent", "Shacal2", "Skipjack", "SM4", "TEA", "Twofish", "Threefish", - "VMPC", "VMPCKSA3", "XTEA", "XSalsa20", "OpenSSLPBKDF", "DSTU7624", "GOST3412_2015", "Zuc" + "VMPC", "VMPCKSA3", "XTEA", "XChaCha20", "XSalsa20", "OpenSSLPBKDF", "DSTU7624", "GOST3412_2015", "Zuc" }; /* diff --git a/prov/src/main/jdk1.1/org/bouncycastle/jce/provider/BouncyCastleProvider.java b/prov/src/main/jdk1.1/org/bouncycastle/jce/provider/BouncyCastleProvider.java index 00dd1bcad8..001c6a022f 100644 --- a/prov/src/main/jdk1.1/org/bouncycastle/jce/provider/BouncyCastleProvider.java +++ b/prov/src/main/jdk1.1/org/bouncycastle/jce/provider/BouncyCastleProvider.java @@ -71,7 +71,7 @@ public final class BouncyCastleProvider extends Provider "AES", "ARC4", "ARIA", "Blowfish", "Camellia", "CAST5", "CAST6", "ChaCha", "DES", "DESede", "GOST28147", "Grainv1", "Grain128", "HC128", "HC256", "IDEA", "Noekeon", "RC2", "RC5", "RC6", "Rijndael", "Salsa20", "SEED", "Serpent", "Shacal2", "Skipjack", "SM4", "TEA", "Twofish", "Threefish", - "VMPC", "VMPCKSA3", "XTEA", "XSalsa20", "OpenSSLPBKDF", "DSTU7624", "GOST3412_2015", "Zuc" + "VMPC", "VMPCKSA3", "XTEA", "XChaCha20", "XSalsa20", "OpenSSLPBKDF", "DSTU7624", "GOST3412_2015", "Zuc" }; /* diff --git a/prov/src/main/jdk1.4/org/bouncycastle/jce/provider/BouncyCastleProvider.java b/prov/src/main/jdk1.4/org/bouncycastle/jce/provider/BouncyCastleProvider.java index 5cc100670f..dd857831de 100644 --- a/prov/src/main/jdk1.4/org/bouncycastle/jce/provider/BouncyCastleProvider.java +++ b/prov/src/main/jdk1.4/org/bouncycastle/jce/provider/BouncyCastleProvider.java @@ -77,7 +77,7 @@ public final class BouncyCastleProvider extends Provider "AES", "ARC4", "ARIA", "Blowfish", "Camellia", "CAST5", "CAST6", "ChaCha", "DES", "DESede", "GOST28147", "Grainv1", "Grain128", "HC128", "HC256", "IDEA", "Noekeon", "RC2", "RC5", "RC6", "Rijndael", "Salsa20", "SEED", "Serpent", "Shacal2", "Skipjack", "SM4", "TEA", "Twofish", "Threefish", - "VMPC", "VMPCKSA3", "XTEA", "XSalsa20", "OpenSSLPBKDF", "DSTU7624", "GOST3412_2015", "Zuc" + "VMPC", "VMPCKSA3", "XTEA", "XChaCha20", "XSalsa20", "OpenSSLPBKDF", "DSTU7624", "GOST3412_2015", "Zuc" }; /* diff --git a/prov/src/test/java/org/bouncycastle/jcajce/provider/test/PrivateConstructorTest.java b/prov/src/test/java/org/bouncycastle/jcajce/provider/test/PrivateConstructorTest.java index fa0b7db67b..a127ce34e4 100644 --- a/prov/src/test/java/org/bouncycastle/jcajce/provider/test/PrivateConstructorTest.java +++ b/prov/src/test/java/org/bouncycastle/jcajce/provider/test/PrivateConstructorTest.java @@ -53,6 +53,7 @@ import org.bouncycastle.jcajce.provider.symmetric.Twofish; import org.bouncycastle.jcajce.provider.symmetric.VMPC; import org.bouncycastle.jcajce.provider.symmetric.VMPCKSA3; +import org.bouncycastle.jcajce.provider.symmetric.XChaCha20; import org.bouncycastle.jcajce.provider.symmetric.XSalsa20; import org.bouncycastle.jcajce.provider.symmetric.XTEA; @@ -84,6 +85,7 @@ public void testSymmetric() evilNoConstructionTest(RC6.class); evilNoConstructionTest(Rijndael.class); evilNoConstructionTest(ChaCha.class); + evilNoConstructionTest(XChaCha20.class); evilNoConstructionTest(Salsa20.class); evilNoConstructionTest(XSalsa20.class); evilNoConstructionTest(SEED.class); diff --git a/prov/src/test/java/org/bouncycastle/jce/provider/test/CipherStreamTest.java b/prov/src/test/java/org/bouncycastle/jce/provider/test/CipherStreamTest.java index 39e37a696b..2c2d33308d 100644 --- a/prov/src/test/java/org/bouncycastle/jce/provider/test/CipherStreamTest.java +++ b/prov/src/test/java/org/bouncycastle/jce/provider/test/CipherStreamTest.java @@ -74,6 +74,18 @@ public class CipherStreamTest + "00000000000000000000000000000000"); private static final byte[] CHA7539OUT = Hex.decode("aef50e541e12a65dc21e90ebb4c03987971c540f78eb536df692ff89fc47561ed17eb23b63eb714c09d0c50af703e01485926c140e994b3edff9df635a91d268"); + private static final byte[] XCHAK = Hex.decode("8000000000000000000000000000000080000000000000000000000000000000"); + private static final byte[] XCHAIV = Hex.decode("000000000000000000000000000000000000000000000000"); + private static final byte[] XCHAIN = Hex.decode( + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000" + + "00000000000000000000000000000000"); + private static final byte[] XCHAOUT = Hex.decode("6d45541f459a2a83ff273e3004084bdd" + + "be6c843425cfd2abaf8ea5870f1d9114" + + "76dd8b4f5e0735094cb28760e21de461" + + "68fa9ac37bb00f327b288cd093cb7a44"); + private static final byte[] HCIN = new byte[64]; private static final byte[] HCIV = new byte[32]; @@ -245,7 +257,7 @@ private void testAlgorithm(String name, byte[] keyBytes, byte[] iv, byte[] plain { isTrue(Arrays.areEqual(iv, in.getIV())); isTrue(Arrays.areEqual(iv, out.getIV())); - + AlgorithmParameters algParams = in.getParameters(); isTrue(Arrays.areEqual(iv, ((IvParameterSpec)algParams.getParameterSpec(IvParameterSpec.class)).getIV())); @@ -253,7 +265,7 @@ private void testAlgorithm(String name, byte[] keyBytes, byte[] iv, byte[] plain algParams = out.getParameters(); isTrue(Arrays.areEqual(iv, ((IvParameterSpec)algParams.getParameterSpec(IvParameterSpec.class)).getIV())); } - + byte[] enc = in.doFinal(plainText); if (!areEqual(enc, cipherText)) { @@ -290,7 +302,7 @@ private void testException( (byte)137, (byte)138, (byte)140, (byte)143 }; byte[] keyBytes; - if (name.equals("HC256") || name.equals("XSalsa20") || name.equals("ChaCha7539") || name.equals("ChaCha20")) + if (name.equals("HC256") || name.equals("XSalsa20") || name.equals("ChaCha7539") || name.equals("ChaCha20") || name.equals("XChaCha20")) { keyBytes = key256; } @@ -414,6 +426,9 @@ public void performTest() runTest("ChaCha20"); testException("ChaCha20"); testAlgorithm("ChaCha20", CHA7539K, CHA7539IV, CHA7539IN, CHA7539OUT); + runTest("XChaCha20"); + testException("XChaCha20"); + testAlgorithm("XChaCha20", XCHAK, XCHAIV, XCHAIN, XCHAOUT); runTest("HC128"); testException("HC128"); testAlgorithm("HC128", HCK128A, HCIV, HCIN, HC128A); diff --git a/prov/src/test/java/org/bouncycastle/jce/provider/test/CipherStreamTest2.java b/prov/src/test/java/org/bouncycastle/jce/provider/test/CipherStreamTest2.java index cc0d2552dd..5348425a8b 100644 --- a/prov/src/test/java/org/bouncycastle/jce/provider/test/CipherStreamTest2.java +++ b/prov/src/test/java/org/bouncycastle/jce/provider/test/CipherStreamTest2.java @@ -520,6 +520,7 @@ private void performTests() "XSalsa20", "ChaCha", "ChaCha7539", + "XChaCha20", "Grainv1", "Grain128", "HC128",