/** * Encrypt a plaintext using the given key and nonce. * * @param nonce a 24-byte nonce (cf. {@link #nonce(ByteString)}, {@link #nonce()}) * @param plaintext an arbitrary message * @return the ciphertext */ public ByteString seal(@Nonnull ByteString nonce, @Nonnull ByteString plaintext) { // initialize XSalsa20 final XSalsa20Engine xsalsa20 = new XSalsa20Engine(); xsalsa20.init(true, new ParametersWithIV(new KeyParameter(key), nonce.toByteArray())); // generate Poly1305 subkey final byte[] sk = new byte[32]; xsalsa20.processBytes(sk, 0, 32, sk, 0); // encrypt plaintext final byte[] out = new byte[plaintext.size() + 16]; xsalsa20.processBytes(plaintext.toByteArray(), 0, plaintext.size(), out, 16); // hash ciphertext and prepend mac to ciphertext final Poly1305 poly1305 = new Poly1305(); poly1305.init(new KeyParameter(sk)); poly1305.update(out, 16, plaintext.size()); poly1305.doFinal(out, 0); return ByteString.of(out); }
private void performTest(int number, TestCase testCase) { final byte[] plaintext = testCase.getPlaintext(); byte[] output = new byte[plaintext.length]; XSalsa20Engine engine = new XSalsa20Engine(); engine.init(false, 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 void performTest() throws Exception { testReset(new Salsa20Engine(), new Salsa20Engine(), new ParametersWithIV(new KeyParameter(random(32)), random(8))); testReset(new Salsa20Engine(), new Salsa20Engine(), new ParametersWithIV(new KeyParameter(random(16)), random(8))); testReset(new XSalsa20Engine(), new XSalsa20Engine(), new ParametersWithIV(new KeyParameter(random(32)), 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 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))); testReset(new HC256Engine(), new HC256Engine(), new ParametersWithIV(new KeyParameter(random(16)), random(16))); testReset(new Grainv1Engine(), new Grainv1Engine(), new ParametersWithIV(new KeyParameter(random(16)), random(8))); testReset(new Grain128Engine(), new Grain128Engine(), new ParametersWithIV(new KeyParameter(random(16)), random(12))); }
/** * Decrypt a ciphertext using the given key and nonce. * * @param nonce a 24-byte nonce * @param ciphertext the encrypted message * @return an {@link Optional} of the original plaintext, or if either the key, nonce, or * ciphertext was modified, an empty {@link Optional} * @see #nonce(ByteString) * @see #nonce() */ public Optional<ByteString> open(@Nonnull ByteString nonce, @Nonnull ByteString ciphertext) { final byte[] in = ciphertext.toByteArray(); final XSalsa20Engine xsalsa20 = new XSalsa20Engine(); final Poly1305 poly1305 = new Poly1305(); // initialize XSalsa20 xsalsa20.init(false, new ParametersWithIV(new KeyParameter(key), nonce.toByteArray())); // generate mac subkey final byte[] sk = new byte[32]; xsalsa20.processBytes(sk, 0, sk.length, sk, 0); // hash ciphertext poly1305.init(new KeyParameter(sk)); final int len = Math.max(ciphertext.size() - 16, 0); poly1305.update(in, 16, len); final byte[] calculatedMAC = new byte[16]; poly1305.doFinal(calculatedMAC, 0); // extract mac final byte[] presentedMAC = new byte[16]; System.arraycopy(in, 0, presentedMAC, 0, Math.min(ciphertext.size(), 16)); // compare macs if (!MessageDigest.isEqual(calculatedMAC, presentedMAC)) { return Optional.empty(); } // decrypt ciphertext final byte[] plaintext = new byte[len]; xsalsa20.processBytes(in, 16, plaintext.length, plaintext, 0); return Optional.of(ByteString.of(plaintext)); }
private void performTests() throws Exception { testModes(new BlowfishEngine(), new BlowfishEngine(), 16); testModes(new DESEngine(), new DESEngine(), 8); testModes(new DESedeEngine(), new DESedeEngine(), 24); testModes(new TEAEngine(), new TEAEngine(), 16); testModes(new CAST5Engine(), new CAST5Engine(), 16); testModes(new RC2Engine(), new RC2Engine(), 16); testModes(new XTEAEngine(), new XTEAEngine(), 16); testModes(new AESEngine(), new AESEngine(), 16); testModes(new NoekeonEngine(), new NoekeonEngine(), 16); testModes(new TwofishEngine(), new TwofishEngine(), 16); testModes(new CAST6Engine(), new CAST6Engine(), 16); testModes(new SEEDEngine(), new SEEDEngine(), 16); testModes(new SerpentEngine(), new SerpentEngine(), 16); testModes(new RC6Engine(), new RC6Engine(), 16); testModes(new CamelliaEngine(), new CamelliaEngine(), 16); testModes(new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512), new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512), 64); testMode(new RC4Engine(), new KeyParameter(new byte[16])); 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 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])); testMode(new HC256Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16])); testSkipping(new Salsa20Engine(), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[8])); testSkipping(new SICBlockCipher(new AESEngine()), new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16])); }
public Base() { super(new XSalsa20Engine(), 24); }