// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.crypto.hpke;

import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.util.Pack;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.Arrays;

public class HPKE
{
    public static final byte mode_base = 0;
    public static final byte mode_psk = 1;
    public static final byte mode_auth = 2;
    public static final byte mode_auth_psk = 3;
    public static final short kem_P256_SHA256 = 16;
    @Deprecated
    public static final short kem_P384_SHA348 = 17;
    public static final short kem_P384_SHA384 = 17;
    public static final short kem_P521_SHA512 = 18;
    public static final short kem_X25519_SHA256 = 32;
    public static final short kem_X448_SHA512 = 33;
    public static final short kdf_HKDF_SHA256 = 1;
    public static final short kdf_HKDF_SHA384 = 2;
    public static final short kdf_HKDF_SHA512 = 3;
    public static final short aead_AES_GCM128 = 1;
    public static final short aead_AES_GCM256 = 2;
    public static final short aead_CHACHA20_POLY1305 = 3;
    public static final short aead_EXPORT_ONLY = -1;
    private final byte[] default_psk;
    private final byte[] default_psk_id;
    private final byte mode;
    private final short kemId;
    private final short kdfId;
    private final short aeadId;
    private final KEM kem;
    private final HKDF hkdf;
    private final int encSize;
    short Nk;
    
    public HPKE(final byte mode, final short kemId, final short kdfId, final short aeadId) {
        this.default_psk = null;
        this.default_psk_id = null;
        this.mode = mode;
        this.kemId = kemId;
        this.kdfId = kdfId;
        this.aeadId = aeadId;
        this.hkdf = new HKDF(kdfId);
        this.kem = new DHKEM(kemId);
        if (aeadId == 1) {
            this.Nk = 16;
        }
        else {
            this.Nk = 32;
        }
        this.encSize = this.kem.getEncryptionSize();
    }
    
    public HPKE(final byte mode, final short kemId, final short kdfId, final short aeadId, final KEM kem, final int encSize) {
        this.default_psk = null;
        this.default_psk_id = null;
        this.mode = mode;
        this.kemId = kemId;
        this.kdfId = kdfId;
        this.aeadId = aeadId;
        this.hkdf = new HKDF(kdfId);
        this.kem = kem;
        if (aeadId == 1) {
            this.Nk = 16;
        }
        else {
            this.Nk = 32;
        }
        this.encSize = encSize;
    }
    
    public int getEncSize() {
        return this.encSize;
    }
    
    public short getAeadId() {
        return this.aeadId;
    }
    
    private void VerifyPSKInputs(final byte b, final byte[] array, final byte[] array2) {
        final boolean b2 = !Arrays.areEqual(array, this.default_psk);
        if (b2 != !Arrays.areEqual(array2, this.default_psk_id)) {
            throw new IllegalArgumentException("Inconsistent PSK inputs");
        }
        if (b2 && b % 2 == 0) {
            throw new IllegalArgumentException("PSK input provided when not needed");
        }
        if (!b2 && b % 2 == 1) {
            throw new IllegalArgumentException("Missing required PSK input");
        }
    }
    
    private HPKEContext keySchedule(final byte b, final byte[] array, final byte[] array2, final byte[] array3, final byte[] array4) {
        this.VerifyPSKInputs(b, array3, array4);
        final byte[] concatenate = Arrays.concatenate(Strings.toByteArray("HPKE"), Pack.shortToBigEndian(this.kemId), Pack.shortToBigEndian(this.kdfId), Pack.shortToBigEndian(this.aeadId));
        final byte[] concatenate2 = Arrays.concatenate(new byte[] { b }, this.hkdf.LabeledExtract(null, concatenate, "psk_id_hash", array4), this.hkdf.LabeledExtract(null, concatenate, "info_hash", array2));
        final byte[] labeledExtract = this.hkdf.LabeledExtract(array, concatenate, "secret", array3);
        return new HPKEContext(new AEAD(this.aeadId, this.hkdf.LabeledExpand(labeledExtract, concatenate, "key", concatenate2, this.Nk), this.hkdf.LabeledExpand(labeledExtract, concatenate, "base_nonce", concatenate2, 12)), this.hkdf, this.hkdf.LabeledExpand(labeledExtract, concatenate, "exp", concatenate2, this.hkdf.getHashSize()), concatenate);
    }
    
    public AsymmetricCipherKeyPair generatePrivateKey() {
        return this.kem.GeneratePrivateKey();
    }
    
    public byte[] serializePublicKey(final AsymmetricKeyParameter asymmetricKeyParameter) {
        return this.kem.SerializePublicKey(asymmetricKeyParameter);
    }
    
    public byte[] serializePrivateKey(final AsymmetricKeyParameter asymmetricKeyParameter) {
        return this.kem.SerializePrivateKey(asymmetricKeyParameter);
    }
    
    public AsymmetricKeyParameter deserializePublicKey(final byte[] array) {
        return this.kem.DeserializePublicKey(array);
    }
    
    public AsymmetricCipherKeyPair deserializePrivateKey(final byte[] array, final byte[] array2) {
        return this.kem.DeserializePrivateKey(array, array2);
    }
    
    public AsymmetricCipherKeyPair deriveKeyPair(final byte[] array) {
        return this.kem.DeriveKeyPair(array);
    }
    
    public byte[][] sendExport(final AsymmetricKeyParameter asymmetricKeyParameter, final byte[] array, final byte[] array2, final int n, final byte[] array3, final byte[] array4, final AsymmetricCipherKeyPair asymmetricCipherKeyPair) {
        final byte[][] array5 = new byte[2][];
        HPKEContextWithEncapsulation hpkeContextWithEncapsulation = null;
        switch (this.mode) {
            case 0: {
                hpkeContextWithEncapsulation = this.setupBaseS(asymmetricKeyParameter, array);
                break;
            }
            case 2: {
                hpkeContextWithEncapsulation = this.setupAuthS(asymmetricKeyParameter, array, asymmetricCipherKeyPair);
                break;
            }
            case 1: {
                hpkeContextWithEncapsulation = this.SetupPSKS(asymmetricKeyParameter, array, array3, array4);
                break;
            }
            case 3: {
                hpkeContextWithEncapsulation = this.setupAuthPSKS(asymmetricKeyParameter, array, array3, array4, asymmetricCipherKeyPair);
                break;
            }
            default: {
                throw new IllegalStateException("Unknown mode");
            }
        }
        array5[0] = hpkeContextWithEncapsulation.encapsulation;
        array5[1] = hpkeContextWithEncapsulation.export(array2, n);
        return array5;
    }
    
    public byte[] receiveExport(final byte[] array, final AsymmetricCipherKeyPair asymmetricCipherKeyPair, final byte[] array2, final byte[] array3, final int n, final byte[] array4, final byte[] array5, final AsymmetricKeyParameter asymmetricKeyParameter) {
        HPKEContext hpkeContext = null;
        switch (this.mode) {
            case 0: {
                hpkeContext = this.setupBaseR(array, asymmetricCipherKeyPair, array2);
                break;
            }
            case 2: {
                hpkeContext = this.setupAuthR(array, asymmetricCipherKeyPair, array2, asymmetricKeyParameter);
                break;
            }
            case 1: {
                hpkeContext = this.setupPSKR(array, asymmetricCipherKeyPair, array2, array4, array5);
                break;
            }
            case 3: {
                hpkeContext = this.setupAuthPSKR(array, asymmetricCipherKeyPair, array2, array4, array5, asymmetricKeyParameter);
                break;
            }
            default: {
                throw new IllegalStateException("Unknown mode");
            }
        }
        return hpkeContext.export(array3, n);
    }
    
    public byte[][] seal(final AsymmetricKeyParameter asymmetricKeyParameter, final byte[] array, final byte[] array2, final byte[] array3, final byte[] array4, final byte[] array5, final AsymmetricCipherKeyPair asymmetricCipherKeyPair) throws InvalidCipherTextException {
        final byte[][] array6 = new byte[2][];
        HPKEContextWithEncapsulation hpkeContextWithEncapsulation = null;
        switch (this.mode) {
            case 0: {
                hpkeContextWithEncapsulation = this.setupBaseS(asymmetricKeyParameter, array);
                break;
            }
            case 2: {
                hpkeContextWithEncapsulation = this.setupAuthS(asymmetricKeyParameter, array, asymmetricCipherKeyPair);
                break;
            }
            case 1: {
                hpkeContextWithEncapsulation = this.SetupPSKS(asymmetricKeyParameter, array, array4, array5);
                break;
            }
            case 3: {
                hpkeContextWithEncapsulation = this.setupAuthPSKS(asymmetricKeyParameter, array, array4, array5, asymmetricCipherKeyPair);
                break;
            }
            default: {
                throw new IllegalStateException("Unknown mode");
            }
        }
        array6[0] = hpkeContextWithEncapsulation.seal(array2, array3);
        array6[1] = hpkeContextWithEncapsulation.getEncapsulation();
        return array6;
    }
    
    public byte[] open(final byte[] array, final AsymmetricCipherKeyPair asymmetricCipherKeyPair, final byte[] array2, final byte[] array3, final byte[] array4, final byte[] array5, final byte[] array6, final AsymmetricKeyParameter asymmetricKeyParameter) throws InvalidCipherTextException {
        HPKEContext hpkeContext = null;
        switch (this.mode) {
            case 0: {
                hpkeContext = this.setupBaseR(array, asymmetricCipherKeyPair, array2);
                break;
            }
            case 2: {
                hpkeContext = this.setupAuthR(array, asymmetricCipherKeyPair, array2, asymmetricKeyParameter);
                break;
            }
            case 1: {
                hpkeContext = this.setupPSKR(array, asymmetricCipherKeyPair, array2, array5, array6);
                break;
            }
            case 3: {
                hpkeContext = this.setupAuthPSKR(array, asymmetricCipherKeyPair, array2, array5, array6, asymmetricKeyParameter);
                break;
            }
            default: {
                throw new IllegalStateException("Unknown mode");
            }
        }
        return hpkeContext.open(array3, array4);
    }
    
    public HPKEContextWithEncapsulation setupBaseS(final AsymmetricKeyParameter asymmetricKeyParameter, final byte[] array) {
        final byte[][] encap = this.kem.Encap(asymmetricKeyParameter);
        return new HPKEContextWithEncapsulation(this.keySchedule((byte)0, encap[0], array, this.default_psk, this.default_psk_id), encap[1]);
    }
    
    public HPKEContextWithEncapsulation setupBaseS(final AsymmetricKeyParameter asymmetricKeyParameter, final byte[] array, final AsymmetricCipherKeyPair asymmetricCipherKeyPair) {
        final byte[][] encap = this.kem.Encap(asymmetricKeyParameter, asymmetricCipherKeyPair);
        return new HPKEContextWithEncapsulation(this.keySchedule((byte)0, encap[0], array, this.default_psk, this.default_psk_id), encap[1]);
    }
    
    public HPKEContext setupBaseR(final byte[] array, final AsymmetricCipherKeyPair asymmetricCipherKeyPair, final byte[] array2) {
        return this.keySchedule((byte)0, this.kem.Decap(array, asymmetricCipherKeyPair), array2, this.default_psk, this.default_psk_id);
    }
    
    public HPKEContextWithEncapsulation SetupPSKS(final AsymmetricKeyParameter asymmetricKeyParameter, final byte[] array, final byte[] array2, final byte[] array3) {
        final byte[][] encap = this.kem.Encap(asymmetricKeyParameter);
        return new HPKEContextWithEncapsulation(this.keySchedule((byte)1, encap[0], array, array2, array3), encap[1]);
    }
    
    public HPKEContext setupPSKR(final byte[] array, final AsymmetricCipherKeyPair asymmetricCipherKeyPair, final byte[] array2, final byte[] array3, final byte[] array4) {
        return this.keySchedule((byte)1, this.kem.Decap(array, asymmetricCipherKeyPair), array2, array3, array4);
    }
    
    public HPKEContextWithEncapsulation setupAuthS(final AsymmetricKeyParameter asymmetricKeyParameter, final byte[] array, final AsymmetricCipherKeyPair asymmetricCipherKeyPair) {
        final byte[][] authEncap = this.kem.AuthEncap(asymmetricKeyParameter, asymmetricCipherKeyPair);
        return new HPKEContextWithEncapsulation(this.keySchedule((byte)2, authEncap[0], array, this.default_psk, this.default_psk_id), authEncap[1]);
    }
    
    public HPKEContext setupAuthR(final byte[] array, final AsymmetricCipherKeyPair asymmetricCipherKeyPair, final byte[] array2, final AsymmetricKeyParameter asymmetricKeyParameter) {
        return this.keySchedule((byte)2, this.kem.AuthDecap(array, asymmetricCipherKeyPair, asymmetricKeyParameter), array2, this.default_psk, this.default_psk_id);
    }
    
    public HPKEContextWithEncapsulation setupAuthPSKS(final AsymmetricKeyParameter asymmetricKeyParameter, final byte[] array, final byte[] array2, final byte[] array3, final AsymmetricCipherKeyPair asymmetricCipherKeyPair) {
        final byte[][] authEncap = this.kem.AuthEncap(asymmetricKeyParameter, asymmetricCipherKeyPair);
        return new HPKEContextWithEncapsulation(this.keySchedule((byte)3, authEncap[0], array, array2, array3), authEncap[1]);
    }
    
    public HPKEContext setupAuthPSKR(final byte[] array, final AsymmetricCipherKeyPair asymmetricCipherKeyPair, final byte[] array2, final byte[] array3, final byte[] array4, final AsymmetricKeyParameter asymmetricKeyParameter) {
        return this.keySchedule((byte)3, this.kem.AuthDecap(array, asymmetricCipherKeyPair, asymmetricKeyParameter), array2, array3, array4);
    }
}
