public EncryptingStream(BlockCipher cipher, OutputStream outputStream) throws EncryptionError, IOException { transformer = new CTRTransformer(cipher, null); this.outputStream = outputStream; outputStream.write(transformer.getIV()); }
public EncryptingStream(Class<? extends BlockCipher> cipherClass, byte[] key, OutputStream outputStream) throws EncryptionError, IOException { this(CTRTransformer.makeCipher(cipherClass, key),outputStream); }
/** * Transform next byte * @param source * @return transformed byte * @throws EncryptionError */ public int transformByte(int source) throws EncryptionError { return (source ^ nextByte()) & 0xFF; }
/** * Create random symmetric key (AES256, CTR) */ public SymmetricKey() { key = CTRTransformer.randomBytes(32); keyInfo = new KeyInfo(KeyInfo.Algorythm.AES256, null, 32); }
/** * Create CTR basic transformer * * @param cipher * properly initialized cipher with key and and direction that must always be set {@link * BlockCipher.Direction#ENCRYPT} * @param iv * null to generate new random IV, get it with {@link #getIV()} and store somewhere with * encrypted data. * * @throws EncryptionError */ public CTRTransformer(BlockCipher cipher, byte[] iv) throws EncryptionError { this.cipher = cipher; blockSize = cipher.getBlockSize(); nonce = iv == null ? randomBytes(blockSize) : iv; counter = 0; source = new byte[blockSize]; counterBytes = new byte[4]; prepareBlock(); }
@Override public void write(int b) throws IOException { try { outputStream.write(transformer.transformByte(b)); } catch (EncryptionError encryptionError) { throw new RuntimeException("can't encrypt data", encryptionError); } }
public DecryptingStream(BlockCipher cipher, InputStream inputStream) throws EncryptionError, IOException { this.inputStream = inputStream; byte[] iv = new byte[cipher.getBlockSize()]; inputStream.read(iv); transformer = new CTRTransformer(cipher, iv); }
private byte nextByte() throws EncryptionError { if (index >= blockSize) prepareBlock(); return source[index++]; }
private void prepareBlock() throws EncryptionError { System.arraycopy(nonce, 0, source, 0, blockSize); counterBytes[0] = (byte) (counter >> 24); counterBytes[1] = (byte) (counter >> 16); counterBytes[2] = (byte) (counter >> 8); counterBytes[3] = (byte) counter; applyXor(source, blockSize - 4, counterBytes); synchronized (cipher) { source = cipher.transformBlock(source); } counter++; index = 0; }
@Test public void bigVolume() throws Exception { SymmetricKey k = new SymmetricKey(); byte[] src = CTRTransformer.randomBytes(0x23456); assertThat(k.decrypt(k.encrypt(src)), equalTo(src)); }
@Override public int read() throws IOException { try { final int i = inputStream.read(); return i >= 0 ? transformer.transformByte(i) : -1; } catch (EncryptionError encryptionError) { throw new IOException("decryption failed", encryptionError); } }
EtaDecryptingStream(InputStream inputStream) throws IOException, EncryptionError { this.inputStream = inputStream; byte[] IV = new byte[getCipher().getBlockSize()]; inputStream.read(IV); transformer = new CTRTransformer(getCipher(), IV); hmac = new HMAC(key); // We should have always block bytes in the buffer to finish: ring = new ByteRingBuffer(hmac.getLength() + 8); for (int i = 0; i < hmac.getLength(); i++) ring.put(inputStream.read()); }
@Test public void decrypt() throws Exception { byte[] src = "FU beyond all r!".getBytes(); assertEquals(16, src.length); byte [] key = CTRTransformer.randomBytes(32); ByteArrayOutputStream bos = new ByteArrayOutputStream(); EncryptingStream es = new EncryptingStream(AES256.class, key, bos); es.write(src); es.write(src); byte[] encrypted = bos.toByteArray(); assertEquals(48, encrypted.length); byte []p1 = Arrays.copyOfRange(encrypted, 0x10, 0x16); byte []p2 = Arrays.copyOfRange(encrypted, 0x20, 0x26); byte []cp = Arrays.copyOfRange(src, 0, 6); assertThat(p1, not(equalTo(p2))); assertThat(cp, not(equalTo(p2))); assertThat(cp, not(equalTo(p1))); byte[] decrypted = DecryptingStream.decrypt(AES256.class, key, encrypted); p1 = Arrays.copyOfRange(decrypted, 0, 16); p2 = Arrays.copyOfRange(decrypted, 16, 32); assertThat(src, equalTo(p1)); assertThat(src, equalTo(p2)); src = "Only5".getBytes(); encrypted = EncryptingStream.encrypt(AES256.class, key, src); assertThat(encrypted.length, equalTo(21)); assertThat(DecryptingStream.decrypt(AES256.class, key, encrypted), equalTo(src)); }
EtaEncryptingStream(OutputStream outputStream, boolean encrypt) throws IOException, EncryptionError { int blockSize = 64; // for SHA256 at least this.outputStream = outputStream; hmac = new HMAC(key); if (encrypt) { transformer = new CTRTransformer(getCipher(), null); outputStream.write(transformer.getIV()); } }
@Override public void write(int plain) throws IOException { if (done) throw new EOFException("can't write past the end()"); try { int encrypted = transformer == null ? plain : transformer.transformByte(plain); hmac.update(encrypted); outputStream.write(encrypted); } catch (EncryptionError encryptionError) { throw new IOException("failed to encrypt", encryptionError); } } }
public DecryptingStream(Class<? extends BlockCipher> cipherClass, byte[] key, InputStream inputStream) throws EncryptionError, IOException { this(CTRTransformer.makeCipher(cipherClass, key), inputStream); }
CTRTransformer.randomBytes(0, 117)); data.put("data", mainKey.etaEncrypt(packedPrivate));
@Override public int read() throws IOException { int nextByte = inputStream.read(); if (nextByte < 0) { readingFinished = true; end(); return -1; } else { ring.put(nextByte); try { int encrypted = ring.get(); hmac.update(encrypted); return transformer.transformByte(encrypted); } catch (EncryptionError encryptionError) { throw new IOException("failed to decrypt", encryptionError); } } }