Search code examples
prolog

How to use crypto_modular_inverse in PROLOG?


I have an assignment where I have to code an Affine Cipher, the thing is, use of the function crypto_modular_inverse is required.

Here's the statement:

D(y) = crypto modular inverse(a) * (y - b) mod m

I searched documentation, but information is scarce and no examples are given.

I need to understand how this function so any nudges is welcomed.


Solution

  • Using this walkthrough of an affine cipher: https://crypto.interactive-maths.com/affine-cipher.html

    D(y) = crypto modular inverse(a) * (y - b) mod m

    For encryption key values a=5 and b=8 and an alphabet of 26 encryptable characters, the crypto modular inverse is

    ?- crypto_modular_inverse(5, 26, C).   % a=5 and alphabet length m=26
    C = 21
    

    I made this, where the maplist lines do the (A*X+B) mod M and cmi(a)*(y-b) mod m transforms along with a dodge around subtracting 97 which is the ASCII Character code of lowercase a to bring the letters down from 97,98,99... to 0,1,2... for the crypto math then adding 97 bringing them back up to printable ASCII characters:

    :- use_module(library(clpfd)).
    
    affine_a_b_plain_to_cipher(A, B, Plain, Cipher) :-
        string_codes(Plain, PlainCodes),
        maplist({A,B}/[N,M]>>(M #= ((A*(N-97)+B) mod 26)+97), PlainCodes, CipherCodes),
        string_codes(Cipher, CipherCodes).
    
    affine_a_b_cipher_to_plain(A, B, Cipher, Plain) :-
        string_codes(Cipher, CipherCodes),
        crypto_modular_inverse(A, 26, C),
        maplist({C,B}/[N,M]>>(M #= (C*((N-97)-B) mod 26)+97), CipherCodes, PlainCodes),
        string_codes(Plain, PlainCodes).
    
    ?- affine_a_b_plain_to_cipher(5, 8, "affine cipher", Cipher).
    Cipher = "ihhwvcvswfrcp"
    
    ?- affine_a_b_cipher_to_plain(5, 8, "ihhwvcvswfrcp", Plain).
    Plain = "affinencipher"
    

    Fixing the alphabet to include space, uppercase, symbols, etc. is left as an exercise for the reader.