示例#1
0
    @Override
    public void write(Cell cell) throws IOException {
      if (encryptor == null) {
        super.write(cell);
        return;
      }

      byte[] iv = nextIv();
      encryptor.setIv(iv);
      encryptor.reset();

      // TODO: Check if this is a cell for an encrypted CF. If not, we can
      // write a 0 here to signal an unwrapped cell and just dump the KV bytes
      // afterward

      StreamUtils.writeRawVInt32(out, iv.length);
      out.write(iv);

      // TODO: Add support for WAL compression

      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      OutputStream cout = encryptor.createEncryptionStream(baos);

      int tlen = cell.getTagsLength();
      // Write the KeyValue infrastructure as VInts.
      StreamUtils.writeRawVInt32(cout, KeyValueUtil.keyLength(cell));
      StreamUtils.writeRawVInt32(cout, cell.getValueLength());
      // To support tags
      StreamUtils.writeRawVInt32(cout, tlen);

      // Write row, qualifier, and family
      StreamUtils.writeRawVInt32(cout, cell.getRowLength());
      cout.write(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
      StreamUtils.writeRawVInt32(cout, cell.getFamilyLength());
      cout.write(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
      StreamUtils.writeRawVInt32(cout, cell.getQualifierLength());
      cout.write(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
      // Write the rest ie. ts, type, value and tags parts
      StreamUtils.writeLong(cout, cell.getTimestamp());
      cout.write(cell.getTypeByte());
      cout.write(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
      if (tlen > 0) {
        cout.write(cell.getTagsArray(), cell.getTagsOffset(), tlen);
      }
      cout.close();

      StreamUtils.writeRawVInt32(out, baos.size());
      baos.writeTo(out);

      // Increment IV given the final payload length
      incrementIv(baos.size());
    }
  /**
   * @param uncompressedBytesWithHeader
   * @param blockType
   * @param headerBytes
   * @throws IOException
   */
  protected void compressAfterEncoding(
      byte[] uncompressedBytesWithHeader, BlockType blockType, byte[] headerBytes)
      throws IOException {
    this.uncompressedBytesWithHeader = uncompressedBytesWithHeader;

    Encryption.Context cryptoContext = fileContext.getEncryptionContext();
    if (cryptoContext != Encryption.Context.NONE) {

      // Encrypted block format:
      // +--------------------------+
      // | byte iv length           |
      // +--------------------------+
      // | iv data ...              |
      // +--------------------------+
      // | encrypted block data ... |
      // +--------------------------+

      cryptoByteStream.reset();
      // Write the block header (plaintext)
      cryptoByteStream.write(headerBytes);

      InputStream in;
      int plaintextLength;
      // Run any compression before encryption
      if (fileContext.getCompression() != Compression.Algorithm.NONE) {
        compressedByteStream.reset();
        compressionStream.resetState();
        compressionStream.write(
            uncompressedBytesWithHeader,
            headerBytes.length,
            uncompressedBytesWithHeader.length - headerBytes.length);
        compressionStream.flush();
        compressionStream.finish();
        byte[] plaintext = compressedByteStream.toByteArray();
        plaintextLength = plaintext.length;
        in = new ByteArrayInputStream(plaintext);
      } else {
        plaintextLength = uncompressedBytesWithHeader.length - headerBytes.length;
        in =
            new ByteArrayInputStream(
                uncompressedBytesWithHeader, headerBytes.length, plaintextLength);
      }

      if (plaintextLength > 0) {

        // Set up the cipher
        Cipher cipher = cryptoContext.getCipher();
        Encryptor encryptor = cipher.getEncryptor();
        encryptor.setKey(cryptoContext.getKey());

        // Set up the IV
        int ivLength = iv.length;
        Preconditions.checkState(ivLength <= Byte.MAX_VALUE, "IV length out of range");
        cryptoByteStream.write(ivLength);
        if (ivLength > 0) {
          encryptor.setIv(iv);
          cryptoByteStream.write(iv);
        }

        // Encrypt the data
        Encryption.encrypt(cryptoByteStream, in, encryptor);

        onDiskBytesWithHeader = cryptoByteStream.toByteArray();

        // Increment the IV given the final block size
        Encryption.incrementIv(iv, 1 + (onDiskBytesWithHeader.length / encryptor.getBlockSize()));

      } else {

        cryptoByteStream.write(0);
        onDiskBytesWithHeader = cryptoByteStream.toByteArray();
      }

    } else {

      if (this.fileContext.getCompression() != NONE) {
        compressedByteStream.reset();
        compressedByteStream.write(headerBytes);
        compressionStream.resetState();
        compressionStream.write(
            uncompressedBytesWithHeader,
            headerBytes.length,
            uncompressedBytesWithHeader.length - headerBytes.length);
        compressionStream.flush();
        compressionStream.finish();
        onDiskBytesWithHeader = compressedByteStream.toByteArray();
      } else {
        onDiskBytesWithHeader = uncompressedBytesWithHeader;
      }
    }

    this.blockType = blockType;
  }
示例#3
0
 protected void incrementIv(int v) {
   Encryption.incrementIv(iv.get(), 1 + (v / encryptor.getBlockSize()));
 }
示例#4
0
 @Override
 protected byte[] initialValue() {
   byte[] iv = new byte[encryptor.getIvLength()];
   new SecureRandom().nextBytes(iv);
   return iv;
 }