"""
Key handling utilities for DSA keys, domain parameters and signatures..
"""

from asn1crypto.algos import DSASignature
from asn1crypto.core import Integer
from asn1crypto.keys import DSAParams

from pkcs11.constants import Attribute
from pkcs11.util import biginteger


def decode_dsa_domain_parameters(der):
    """
    Decode RFC 3279 DER-encoded Dss-Params.

    :param bytes der: DER-encoded parameters
    :rtype: dict(Attribute,*)
    """

    params = DSAParams.load(der)

    return {
        Attribute.BASE: biginteger(params["g"]),
        Attribute.PRIME: biginteger(params["p"]),
        Attribute.SUBPRIME: biginteger(params["q"]),
    }


def encode_dsa_domain_parameters(obj):
    """
    Encode RFC 3279 DER-encoded Dss-Params.

    :param DomainParameters obj: domain parameters
    :rtype: bytes
    """
    asn1 = DSAParams(
        {
            "g": int.from_bytes(obj[Attribute.BASE], byteorder="big"),
            "p": int.from_bytes(obj[Attribute.PRIME], byteorder="big"),
            "q": int.from_bytes(obj[Attribute.SUBPRIME], byteorder="big"),
        }
    )

    return asn1.dump()


def encode_dsa_public_key(key):
    """
    Encode DSA public key into RFC 3279 DER-encoded format.

    :param PublicKey key: public key
    :rtype: bytes
    """

    asn1 = Integer(int.from_bytes(key[Attribute.VALUE], byteorder="big"))

    return asn1.dump()


def decode_dsa_public_key(der):
    """
    Decode a DSA public key from RFC 3279 DER-encoded format.

    Returns a `biginteger` encoded as bytes.

    :param bytes der: DER-encoded public key
    :rtype: bytes
    """

    asn1 = Integer.load(der)

    return biginteger(asn1)


def encode_dsa_signature(signature):
    """
    Encode a signature (generated by :meth:`pkcs11.SignMixin.sign`) into
    DER-encoded ASN.1 (Dss_Sig_Value) format.

    :param bytes signature: signature as bytes
    :rtype: bytes
    """

    asn1 = DSASignature.from_p1363(signature)

    return asn1.dump()


def decode_dsa_signature(der):
    """
    Decode a DER-encoded ASN.1 (Dss_Sig_Value) signature (as generated by
    OpenSSL/X.509) into PKCS #11 format.

    :param bytes der: DER-encoded signature
    :rtype bytes:
    """

    asn1 = DSASignature.load(der)

    return asn1.to_p1363()
