import asn1tools
import os.path

__dir__ = os.path.dirname(os.path.realpath(__file__))


def hex_to_der(p: str, g: int=2) -> bytearray:
    # only accept generators of 2 and 5
    if g not in (2, 5):
        raise ValueError("invalid generator")

    # compile the asn1 specification
    path = os.path.join(__dir__, "dhparam.asn")
    encoder = asn1tools.compile_files(path)

    # remove formatting and convert hex to integer
    p = p.replace(" ", "").replace("\n", "")
    p = int(p, 16)

    return encoder.encode("DHParameter", {
        "prime": p,
        "base": g,
    })


def test_known_good_ffdhe(p, g, filename):
    der = hex_to_der(p, g)

    # read in the known good ffdhe2048.der file
    filename = os.path.join(__dir__, "tests", filename)
    with open(filename, "rb") as f:
        known_good_der = f.read()

    assert der == known_good_der


if __name__ == "__main__":
    # 1024-bit, from RFC 5996
    p = """
        FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
        29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
        EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
        E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
        EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381
        FFFFFFFF FFFFFFFF
    """
    test_known_good_ffdhe(p, 2, "1024.rfc5996.der")

    # 2048-bit, from RFC 7919
    p = """
        FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
        D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
        7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
        2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
        984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
        30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
        B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
        0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
        9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
        3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
        886B4238 61285C97 FFFFFFFF FFFFFFFF
    """
    test_known_good_ffdhe(p, 2, "2048.rfc7919.der")

    # 4096-bit, from RFC 3526
    p = """
       FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
       29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
       EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
       E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
       EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
       C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
       83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
       670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
       E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
       DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
       15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64
       ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7
       ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B
       F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C
       BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31
       43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7
       88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA
       2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6
       287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED
       1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9
       93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199
       FFFFFFFF FFFFFFFF
    """
    test_known_good_ffdhe(p, 2, "4096.rfc3526.der")

    # 4096-bit, from RFC 7919
    p = """
        FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
        D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
        7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
        2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
        984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
        30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
        B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
        0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
        9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
        3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
        886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238
        61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C
        AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3
        64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D
        ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF
        3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB
        7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004
        87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832
        A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A
        1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF
        8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E655F6A
        FFFFFFFF FFFFFFFF
    """
    test_known_good_ffdhe(p, 2, "4096.rfc7919.der")

    # If you wanted to write a given 'p' to a file:

    # der = hex_to_der(p, 2)
    # path = os.path.join(__dir__, "tests", "4096.rfc7919.der")
    # with open(path, "wb") as f:
    #     f.write(der)
