// Path: lib/src/main/java/com/google/capillary/RsaEcdsaConstants.java
// public enum Padding {
//   OAEP("OAEPPadding"),
//   PKCS1("PKCS1Padding");
// 
//   private static final String PREFIX = "RSA/ECB/";
// 
//   private final String padding;
// 
//   Padding(String val) {
//     padding = val;
//   }
// 
//   /**
//    * Returns the current padding enum's transformation string that should be used when calling
//    * {@code javax.crypto.Cipher.getInstance}.
//    *
//    * @return the transformation string.
//    */
//   public String getTransformation() {
//     return PREFIX + padding;
//   }
// }


import com.google.capillary.RsaEcdsaConstants.Padding;
import com.google.crypto.tink.HybridEncrypt;
import com.google.crypto.tink.PublicKeySign;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
import javax.crypto.spec.OAEPParameterSpec;
/*
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.capillary;


/**
 * A {@link HybridEncrypt} implementation for an authenticated hybrid encryption scheme, which is
 * called RSA-ECDSA for simplicity, that is based on RSA public-key encryption, AES symmetric key
 * encryption in GCM mode (AES-GCM), and ECDSA signature algorithm.
 *
 * <p>Sample usage:
 * <pre>{@code
 * import com.google.capillary.RsaEcdsaConstants.Padding;
 * import com.google.crypto.tink.HybridDecrypt;
 * import com.google.crypto.tink.HybridEncrypt;
 * import com.google.crypto.tink.PublicKeySign;
 * import com.google.crypto.tink.PublicKeyVerify;
 * import java.security.PrivateKey;
 * import java.security.PublicKey;
 *
 * // Encryption.
 * PublicKeySign senderSigner = ...;
 * PublicKey recipientPublicKey = ...;
 * HybridEncrypt hybridEncrypt = new RsaEcdsaHybridEncrypt.Builder()
 *   .withSenderSigner(senderSigner)
 *   .withRecipientPublicKey(recipientPublicKey)
 *   .withPadding(Padding.OAEP)
 *   .build();
 * byte[] plaintext = ...;
 * byte[] ciphertext = hybridEncrypt.encrypt(plaintext, null);
 *
 * // Decryption.
 * PublicKeyVerify senderVerifier = ...;
 * PrivateKey recipientPrivateKey = ...;
 * HybridDecrypt hybridDecrypt = new RsaEcdsaHybridDecrypt.Builder()
 *   .withSenderVerifier(senderVerifier)
 *   .withRecipientPrivateKey(recipientPrivateKey)
 *   .withPadding(Padding.OAEP)
 *   .build();
 * byte[] ciphertext = ...;
 * byte[] plaintext = hybridDecrypt.decrypt(ciphertext, null);
 * }</pre>
 *
 * <p>The encryption algorithm consists of the following steps:
 * <ol>
 * <li>Generate an AES-GCM symmetric key.</li>
 * <li>Encrypt the AES-GCM key using RSA.</li>
 * <li>Encrypt the message using the AES-GCM key.</li>
 * <li>Encode the encrypted AES-GCM key and the encrypted message into a byte array A1.</li>
 * <li>Sign A1 using ECDSA.</li>
 * <li>Combine A1 and its signature into a byte array A2.</li>
 * <li>Output A2 as the RSA-ECDSA ciphertext.</li>
 * </ol>
 *
 * <p>The format of the RsaEcdsa ciphertext is the following:
 * <pre>{@code
 * +------------------------------------------+
 * | ECDSA Signature Length (4 bytes)         |
 * +------------------------------------------+
 * | ECDSA Signature                          |
 * +------------------------------------------+
 * | RSA+AES-GCM hybrid-encryption ciphertext |
 * +------------------------------------------+
 * }</pre>
 *
 * <p>This implementation of RSA-ECDSA depends on the <a href="https://github.com/google/tink"
 * target="_blank">Tink</a> crypto library to perform AES-GCM and ECDSA operations.
 */
public final class RsaEcdsaHybridEncrypt implements HybridEncrypt {

  private final PublicKeySign senderSigner;
  private final PublicKey recipientPublicKey;
// Path: lib/src/main/java/com/google/capillary/RsaEcdsaConstants.java
// public enum Padding {
//   OAEP("OAEPPadding"),
//   PKCS1("PKCS1Padding");
// 
//   private static final String PREFIX = "RSA/ECB/";
// 
//   private final String padding;
// 
//   Padding(String val) {
//     padding = val;
//   }
// 
//   /**
//    * Returns the current padding enum's transformation string that should be used when calling
//    * {@code javax.crypto.Cipher.getInstance}.
//    *
//    * @return the transformation string.
//    */
//   public String getTransformation() {
//     return PREFIX + padding;
//   }
// }


// Path: lib/src/main/java/com/google/capillary/RsaEcdsaHybridEncrypt.java
import com.google.capillary.RsaEcdsaConstants.Padding;
import com.google.crypto.tink.HybridEncrypt;
import com.google.crypto.tink.PublicKeySign;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
import javax.crypto.spec.OAEPParameterSpec;

/*
 * Copyright 2018 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.capillary;


/**
 * A {@link HybridEncrypt} implementation for an authenticated hybrid encryption scheme, which is
 * called RSA-ECDSA for simplicity, that is based on RSA public-key encryption, AES symmetric key
 * encryption in GCM mode (AES-GCM), and ECDSA signature algorithm.
 *
 * <p>Sample usage:
 * <pre>{@code
 * import com.google.capillary.RsaEcdsaConstants.Padding;
 * import com.google.crypto.tink.HybridDecrypt;
 * import com.google.crypto.tink.HybridEncrypt;
 * import com.google.crypto.tink.PublicKeySign;
 * import com.google.crypto.tink.PublicKeyVerify;
 * import java.security.PrivateKey;
 * import java.security.PublicKey;
 *
 * // Encryption.
 * PublicKeySign senderSigner = ...;
 * PublicKey recipientPublicKey = ...;
 * HybridEncrypt hybridEncrypt = new RsaEcdsaHybridEncrypt.Builder()
 *   .withSenderSigner(senderSigner)
 *   .withRecipientPublicKey(recipientPublicKey)
 *   .withPadding(Padding.OAEP)
 *   .build();
 * byte[] plaintext = ...;
 * byte[] ciphertext = hybridEncrypt.encrypt(plaintext, null);
 *
 * // Decryption.
 * PublicKeyVerify senderVerifier = ...;
 * PrivateKey recipientPrivateKey = ...;
 * HybridDecrypt hybridDecrypt = new RsaEcdsaHybridDecrypt.Builder()
 *   .withSenderVerifier(senderVerifier)
 *   .withRecipientPrivateKey(recipientPrivateKey)
 *   .withPadding(Padding.OAEP)
 *   .build();
 * byte[] ciphertext = ...;
 * byte[] plaintext = hybridDecrypt.decrypt(ciphertext, null);
 * }</pre>
 *
 * <p>The encryption algorithm consists of the following steps:
 * <ol>
 * <li>Generate an AES-GCM symmetric key.</li>
 * <li>Encrypt the AES-GCM key using RSA.</li>
 * <li>Encrypt the message using the AES-GCM key.</li>
 * <li>Encode the encrypted AES-GCM key and the encrypted message into a byte array A1.</li>
 * <li>Sign A1 using ECDSA.</li>
 * <li>Combine A1 and its signature into a byte array A2.</li>
 * <li>Output A2 as the RSA-ECDSA ciphertext.</li>
 * </ol>
 *
 * <p>The format of the RsaEcdsa ciphertext is the following:
 * <pre>{@code
 * +------------------------------------------+
 * | ECDSA Signature Length (4 bytes)         |
 * +------------------------------------------+
 * | ECDSA Signature                          |
 * +------------------------------------------+
 * | RSA+AES-GCM hybrid-encryption ciphertext |
 * +------------------------------------------+
 * }</pre>
 *
 * <p>This implementation of RSA-ECDSA depends on the <a href="https://github.com/google/tink"
 * target="_blank">Tink</a> crypto library to perform AES-GCM and ECDSA operations.
 */
public final class RsaEcdsaHybridEncrypt implements HybridEncrypt {

  private final PublicKeySign senderSigner;
  private final PublicKey recipientPublicKey;
  private final Padding padding;