public byte[] processBlock(byte[] in, int inOff, int len) throws InvalidCipherTextException {
        if (param instanceof SHEBV11bPublicKeyParameters) {
            // Enc

            SHEBV11bPublicKeyParameters pk = ((SHEBV11bPublicKeyParameters) param);
            SHEBV11bParameters parameters = pk.getParameters();

            // Load the message
            Element m = parameters.getRq().newElement();
            m.setFromBytes(in, inOff);

            // Choose the randomness
            Element u = parameters.sample();
            Element f = parameters.sample().mul(parameters.getT());
            Element g = parameters.sample().mul(parameters.getT());

            // Encrypt
            Element c0 = pk.getA0().mul(u).add(g).add(m);
            Element c1 = pk.getA1().mul(u).add(f);

            return ElementUtils.toByteArray(c0, c1);
        } else if (param instanceof SHEBV11bAddParameters) {
            // Add
            SHEBV11bPublicKeyParameters pk = ((SHEBV11bAddParameters) param).getPk();
            SHEBV11bParameters parameters = pk.getParameters();

            // Load left part
            Element[] left = new Element[2];
            left[0] = parameters.getRq().newElement();
            inOff += left[0].setFromBytes(in, inOff);
            left[1] = parameters.getRq().newElement();
            inOff += left[1].setFromBytes(in, inOff);

            // Load right part
            Element[] right = new Element[2];
            right[0] = parameters.getRq().newElement();
            inOff += right[0].setFromBytes(in, inOff);
            right[1] = parameters.getRq().newElement();
            inOff += right[1].setFromBytes(in, inOff);

            // Sum
            for (int i = 0; i < 1; i++) {
                left[0].add(right[0]);
                left[1].add(right[1]);
            }
            return ElementUtils.toByteArray(left[0], left[1]);
        } else if (param instanceof SHEBV11bMulParameters) {
            // Mul

            SHEBV11bPublicKeyParameters pk = ((SHEBV11bMulParameters) param).getPk();
            SHEBV11bParameters parameters = pk.getParameters();

            // Load left
            Element[] left = new Element[2];
            left[0] = parameters.getRq().newElement();
            inOff += left[0].setFromBytes(in, inOff);
            left[1] = parameters.getRq().newElement();
            inOff += left[1].setFromBytes(in, inOff);

            // Load right
            Element[] right = new Element[2];
            right[0] = parameters.getRq().newElement();
            inOff += right[0].setFromBytes(in, inOff);
            right[1] = parameters.getRq().newElement();
            inOff += right[1].setFromBytes(in, inOff);

            // Multiply
            Element c0 = left[0].duplicate().mul(right[0]);
            Element c1 = left[0].duplicate().mul(right[1]).add(left[1].duplicate().mul(right[0]));
            Element c2 = left[1].duplicate().mul(right[1]);

            // Relinearize
            Element[] c2s = decompose(parameters, c2);

            Element c1Lin = c1.duplicate();
            Element c0Lin = c0.duplicate();
            for (int i = 0; i < parameters.getLub(); i++) {
                c1Lin.add(c2s[i].duplicate().mul(pk.getAAt(i)));
                c0Lin.add(c2s[i].duplicate().mul(pk.getBAt(i)));
            }

            return ElementUtils.toByteArray(c0Lin, c1Lin);
        } else if (param instanceof SHEBV11bSecretKeyParameters) {
            // Dec

            SHEBV11bSecretKeyParameters sk = ((SHEBV11bSecretKeyParameters) param);
            SHEBV11bParameters parameters = sk.getParameters();

            // Load the ciphertext
            Element[] elements = new Element[2];
            elements[0] = parameters.getRq().newElement();
            inOff += elements[0].setFromBytes(in, inOff);
            elements[1] = parameters.getRq().newElement();
            inOff += elements[1].setFromBytes(in, inOff);

            // Decrypt
            return elements[0].add(elements[1].mul(sk.getSecretKey())).mod(parameters.getT()).toBytes();
        }

        throw new IllegalStateException("Invalid parameters.");
    }