/** * Computes the xor of two byte arrays of equal size. * * @return a new byte[] of length x.length. */ public static final byte[] xor(final byte[] x, final byte[] y) { if (x.length != y.length) { throw new IllegalArgumentException("The lengths of x and y should match."); } return xor(x, 0, y, 0, x.length); }
/** * s2v per https://tools.ietf.org/html/rfc5297 * * @param s * @return s2v(si) * @throws GeneralSecurityException */ private byte[] s2v(final byte[]... s) throws GeneralSecurityException { if (s.length == 0) { // Should never happen with AES-SIV, but we include this for completeness. return cmacForS2V.computeMac(BLOCK_ONE); } byte[] result = cmacForS2V.computeMac(BLOCK_ZERO); for (int i = 0; i < s.length - 1; i++) { result = Bytes.xor(AesUtil.dbl(result), cmacForS2V.computeMac(s[i])); } byte[] lastBlock = s[s.length - 1]; if (lastBlock.length >= 16) { result = Bytes.xorEnd(lastBlock, result); } else { result = Bytes.xor(AesUtil.cmacPad(lastBlock), AesUtil.dbl(result)); } return cmacForS2V.computeMac(result); }
private void process(final byte[] nonce, ByteBuffer output, ByteBuffer input) throws GeneralSecurityException { int length = input.remaining(); int numBlocks = (length / BLOCK_SIZE_IN_BYTES) + 1; for (int i = 0; i < numBlocks; i++) { ByteBuffer keyStreamBlock = getKeyStreamBlock(nonce, i + initialCounter); if (i == numBlocks - 1) { // last block Bytes.xor( output, input, keyStreamBlock, length % BLOCK_SIZE_IN_BYTES); } else { Bytes.xor( output, input, keyStreamBlock, BLOCK_SIZE_IN_BYTES); } } }
mLast = Bytes.xor(data, (n - 1) * AesUtil.BLOCK_SIZE, subKey1, 0, AesUtil.BLOCK_SIZE); } else { mLast = Bytes.xor( AesUtil.cmacPad(Arrays.copyOfRange(data, (n - 1) * AesUtil.BLOCK_SIZE, data.length)), subKey2); y = Bytes.xor(x, 0, data, i * AesUtil.BLOCK_SIZE, AesUtil.BLOCK_SIZE); x = aes.doFinal(y); y = Bytes.xor(mLast, x);