@Override
  public byte[] encrypt(final byte[] plaintext, final byte[] associatedData)
      throws GeneralSecurityException {
    if (plaintext == null) {
      throw new NullPointerException("plaintext is null");
    }
    byte[] nonce = Random.randBytes(NONCE_SIZE_IN_BYTES);
    AlgorithmParameterSpec params = new IvParameterSpec(nonce);
    Cipher cipher = localCipher.get();
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, params);
    if (associatedData != null && associatedData.length != 0) {
      cipher.updateAAD(associatedData);
    }
    int outputSize = cipher.getOutputSize(plaintext.length);
    if (outputSize > Integer.MAX_VALUE - outputPrefix.length - NONCE_SIZE_IN_BYTES) {
      throw new GeneralSecurityException("plaintext too long");
    }
    int len = outputPrefix.length + NONCE_SIZE_IN_BYTES + outputSize;
    byte[] output = Arrays.copyOf(outputPrefix, len);
    System.arraycopy(
        /* src= */ nonce,
        /* srcPos= */ 0,
        /* dest= */ output,
        /* destPos= */ outputPrefix.length,
        /* length= */ NONCE_SIZE_IN_BYTES);
    int written =
        cipher.doFinal(
            plaintext, 0, plaintext.length, output, outputPrefix.length + NONCE_SIZE_IN_BYTES);
    if (written != outputSize) {
      throw new GeneralSecurityException("not enough data written");
    }
    return output;
  }
Returns a thread-local instance of the ChaCha20Poly1305, or null if ChaCha20Poly1305 is
not supported.
java_src/src/main/java/com/google/crypto/tink/aead/internal/ChaCha20Poly1305Jce.java