// Path: src/main/java/org/cryptomator/cryptolib/common/Destroyables.java
// public class Destroyables {
// 
// 	private Destroyables() {
// 	}
// 
// 	public static void destroySilently(Destroyable destroyable) {
// 		if (destroyable == null) {
// 			return;
// 		}
// 		try {
// 			destroyable.destroy();
// 		} catch (DestroyFailedException e) {
// 			// no-op
// 		}
// 	}
// 
// }


import org.cryptomator.cryptolib.common.Destroyables;
import javax.crypto.AEADBadTagException;
import javax.crypto.KeyAgreement;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.util.Arrays;
package org.cryptomator.cryptolib.ecies;



public class ECIntegratedEncryptionScheme {

	/**
	 * The ECIES used in Cryptomator Hub:
	 * <ul>
	 *     <li>To be used with {@link org.cryptomator.cryptolib.common.P384KeyPair P-384 EC keys}</li>
	 *     <li>Use ANSI X9.63 KDF with SHA-256 to derive a 352 bit shared secret</li>
	 *     <li>Cut shared secret into 256 bit key + 96 bit nonce used for AES-GCM to encrypt/decrypt</li>
	 * </ul>
	 */
	public static final ECIntegratedEncryptionScheme HUB = new ECIntegratedEncryptionScheme(AuthenticatedEncryption.GCM_WITH_SECRET_NONCE, KeyDerivationFunction.ANSI_X963_SHA256_KDF);

	private final AuthenticatedEncryption ae;
	private final KeyDerivationFunction kdf;

	public ECIntegratedEncryptionScheme(AuthenticatedEncryption ae, KeyDerivationFunction kdf) {
		this.ae = ae;
		this.kdf = kdf;
	}

	public EncryptedMessage encrypt(KeyPairGenerator ephKeyGen, ECPublicKey receiverPublicKey, byte[] plaintext) {
		KeyPair ephKeyPair = ephKeyGen.generateKeyPair();
		try {
			if (ephKeyPair.getPrivate() instanceof ECPrivateKey) {
				assert ephKeyPair.getPublic() instanceof ECPublicKey;
				byte[] ciphertext = encrypt((ECPrivateKey) ephKeyPair.getPrivate(), receiverPublicKey, plaintext);
				return new EncryptedMessage((ECPublicKey) ephKeyPair.getPublic(), ciphertext);
			} else {
				throw new IllegalArgumentException("key generator didn't create EC key pair");
			}
		} finally {
// Path: src/main/java/org/cryptomator/cryptolib/common/Destroyables.java
// public class Destroyables {
// 
// 	private Destroyables() {
// 	}
// 
// 	public static void destroySilently(Destroyable destroyable) {
// 		if (destroyable == null) {
// 			return;
// 		}
// 		try {
// 			destroyable.destroy();
// 		} catch (DestroyFailedException e) {
// 			// no-op
// 		}
// 	}
// 
// }


// Path: src/main/java/org/cryptomator/cryptolib/ecies/ECIntegratedEncryptionScheme.java
import org.cryptomator.cryptolib.common.Destroyables;
import javax.crypto.AEADBadTagException;
import javax.crypto.KeyAgreement;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.util.Arrays;

package org.cryptomator.cryptolib.ecies;



public class ECIntegratedEncryptionScheme {

	/**
	 * The ECIES used in Cryptomator Hub:
	 * <ul>
	 *     <li>To be used with {@link org.cryptomator.cryptolib.common.P384KeyPair P-384 EC keys}</li>
	 *     <li>Use ANSI X9.63 KDF with SHA-256 to derive a 352 bit shared secret</li>
	 *     <li>Cut shared secret into 256 bit key + 96 bit nonce used for AES-GCM to encrypt/decrypt</li>
	 * </ul>
	 */
	public static final ECIntegratedEncryptionScheme HUB = new ECIntegratedEncryptionScheme(AuthenticatedEncryption.GCM_WITH_SECRET_NONCE, KeyDerivationFunction.ANSI_X963_SHA256_KDF);

	private final AuthenticatedEncryption ae;
	private final KeyDerivationFunction kdf;

	public ECIntegratedEncryptionScheme(AuthenticatedEncryption ae, KeyDerivationFunction kdf) {
		this.ae = ae;
		this.kdf = kdf;
	}

	public EncryptedMessage encrypt(KeyPairGenerator ephKeyGen, ECPublicKey receiverPublicKey, byte[] plaintext) {
		KeyPair ephKeyPair = ephKeyGen.generateKeyPair();
		try {
			if (ephKeyPair.getPrivate() instanceof ECPrivateKey) {
				assert ephKeyPair.getPublic() instanceof ECPublicKey;
				byte[] ciphertext = encrypt((ECPrivateKey) ephKeyPair.getPrivate(), receiverPublicKey, plaintext);
				return new EncryptedMessage((ECPublicKey) ephKeyPair.getPublic(), ciphertext);
			} else {
				throw new IllegalArgumentException("key generator didn't create EC key pair");
			}
		} finally {
			Destroyables.destroySilently(ephKeyPair.getPrivate());