# cython: language_level = 3

import sys
from libc.stdlib cimport malloc
from libc.string cimport memcpy, strlen, memset

cdef extern from "openssl/sha.h":
    void SHA512_Init(void *)
    void SHA512_Update(void *, const void *, size_t)
    int SHA512_Final(unsigned char *, void *)
    cdef union u:
        unsigned long long d[16]
        unsigned char p[16*8]
    ctypedef struct SHA512_CTX:
        unsigned long long h[8]
        unsigned long long Nl, Nh
        u u
        unsigned int num, md_len



cdef sha512(const char *string, char output_buffer[129]):
    cdef unsigned char hash[64]
    cdef SHA512_CTX sha512
    SHA512_Init(&sha512)
    SHA512_Update(&sha512, string, strlen(string))
    SHA512_Final(hash, &sha512)
    cdef int i
    cdef const char *hex = "0123456789abcdef";
    for i in range(64):
        output_buffer[i * 2] = hex[hash[i] // 16]
        output_buffer[i * 2 + 1] = hex[hash[i] % 16]
    output_buffer[128] = 0


cpdef search():
    cdef int repeat = 10
    cdef char *suffix = b"AFPy"
    cdef unsigned int size = repeat + strlen(suffix)
    cdef char *candidate = <char *> malloc(size + 1)
    cdef char *digest;
    cdef char output_buffer[129];
    memset(candidate, b'-', size)
    memcpy(candidate + size - strlen(suffix), suffix, strlen(suffix))
    candidate[size] = 0

    cdef unsigned int i = 0;
    while True:
        candidate[9] = i % 58 + 65;
        candidate[8] = <char>(i / 58 ** 1) % 58 + 65;
        candidate[7] = <char>(i / 58 ** 2) % 58 + 65;
        candidate[6] = <char>(i / 58 ** 3) % 58 + 65;
        candidate[5] = <char>(i / 58 ** 4) % 58 + 65;
        candidate[4] = <char>(i / 58 ** 5) % 58 + 65;
        candidate[3] = <char>(i / 58 ** 6) % 58 + 65;
        candidate[2] = <char>(i / 58 ** 7) % 58 + 65;
        candidate[1] = <char>(i / 58 ** 8) % 58 + 65;
        candidate[0] = <char>(i / 58 ** 9) % 58 + 65;
        i += 1
        sha512(candidate, output_buffer)
        if output_buffer.startswith(b"00000"):
            print(f"sha512({candidate!r}) = {output_buffer}")
            sys.exit(0)
    print("Not found")
