Review Show
Goal: Public Key Encryption
Review: | Newish: |
---|---|
- RSA | - modexp |
- FileIO |
- In the lab you should’ve finished key generation.
- Otherwise, return to a complete the lab.
- KeyGen
- This assignment concerns two distinct executable files:
- Write keys to files
keygen.c
- Covered in the lab section.
- Encrpyt and decrypt based those keys.
rsainc.c
- Covered here, but requiring
keygen.c
- Write keys to files
KeyGen Show
- This section summarizes the lab. If you completed the lab, you may move onto “ModExp”
- Recall a sample Python implementation was provided, but was not very readable.
A Private Key in 3 Parts
- We recall that the private key minimally contains:
n
, a modular basee
, an encryptor, andd
, a descryptor.
- Based on the KeyGen lab, it should be uncomplicated to calculate these values for 64 bit keys.
- We will use
.bad
instead of.pem
and insecurely store these values in plaintext. - We will then make executables to generate
.bad
and encrypt content provided a.bad
- We name a
.bad
so helpfully we don’t use it by accident.
- We name a
- We will naively print 3 lines of hexademical values,
n
,e
, thend
. - We will write them to a 5-line file as follows:
- The first line is the precise header text.
- The second line is the
n
value in hexadecimal. - The third line is the
e
value, which is10001
. - The fourth line is the
d
value, which should be kept secret. - The fifth and final line is the precise footer text.
unsafe.bad
-----BEGIN UNSAFE PRIVATE KEY-----
95a61f99198bd8e9
10001
fbea5e6a3ed31e8f -----END UNSAFE PRIVATE KEY-----
A Public Key in 2 Parts
- We recall that the public key contains, and should only contain:
n
, a modular base, ande
, an encryptor
- Based on the KeyGen lab, we already have the ability to write these values to file.
- We will use
.pub
instead of.pem
or.bad
- Not a huge deal how these are stored, actually.
- The key itself though, is still unsafe to use.
- We will naively print 2 lines of hexademical values,
n
, thene
. - We will right them to a file prefixed and suffixed as follows:
unsafe.pub
-----BEGIN UNSAFE PUBLIC KEY-----
95a61f99198bd8e9
10001 -----END UNSAFE PUBLIC KEY-----
- Ensure your keys are 32 bit.
- Simply encrypt values up to
1 << 31
in size.
- Simply encrypt values up to
- Here is a testing script:
def modexp(m, e, n):
if e == 0:
return 1
if e == 1:
return m % n
if e % 2:
return (m * modexp(m*m % n, e//2, n)) % n
return modexp(m*m % n, e//2, n) % n
= lambda e, n : lambda m : modexp(m,e,n)
make_encrypt
= open("unsafe.bad").readlines()
lines = int(lines[1], 16)
n = int(lines[2], 16)
e = int(lines[3], 16)
d
= open("unsafe.pub").readlines()
lines if n != int(lines[1], 16) or e != int(lines[2], 16):
print("Public key does not match private key.")
exit()
= make_encrypt(e,n)
encrypt = make_encrypt(d,n)
decrypt
if all([i == decrypt(encrypt(i)) for i in range(0x100)]):
print("Keys work for small values.")
else:
print("Keys failed on small values.")
if all([i == decrypt(encrypt(i)) for i in range(0,1 << 31, 1 << 29)]):
print("Keys work for larger values.")
else:
print("Keys failed on larger values.")
By successfully encrypting and decrypting up to
1 << 31
, the key is large enough for some small tasks, such encrypting the string “hi” - a string of length 3 when including the null terminator, which therefore contains 24 bits of information.
ModExp Show
- For C language encryption and decryption, it is necessary to implement “modexp” in C.
- Do so in a novel file,
rsainc.c
, which should:- Accept 3 command line arguments:
- A flag
-d
or-e
for decrypt or encrypt - The file name of an input file.
- The file name of an output file.
- A flag
- It should:
- Read the content of the input file.
- Encrypt or decrypt, as specified, the file contents.
- It should read
n
andd
from “unsafe.bad” to decrypt. - It should read
n
ande
from “unsafe.pub” to encrypt.
- It should read
- Write the encrypted or decrypted content to the output file.
- Accept 3 command line arguments:
- Here is a Python implementation.
- It is exceptionally annoying because Python doesn’t like to treat files as holding data rather than text.
rsa_py.py
if __name__ != "__main__":
exit()
import sys
def modexp(m, e, n):
if e == 0:
return 1
if e == 1:
return m % n
if e % 2:
return (m * modexp(m*m % n, e//2, n)) % n
return modexp(m*m % n, e//2, n) % n
if 'e' in sys.argv[1]:
= open("unsafe.pub").readlines()
lines = int(lines[1], 16), int(lines[2], 16)
n, e elif 'd' in sys.argv[1]:
= open("unsafe.bad").readlines()
lines = int(lines[1], 16), int(lines[3], 16) # have to call it e, not d
n, e else:
exit()= open(sys.argv[2], "rb").read()
s = int.from_bytes(s, byteorder=sys.byteorder, signed=False)
m = modexp(m,e,n)
c = open(sys.argv[3], "wb").write(c.to_bytes(4, byteorder=sys.byteorder)) s
Hint
- You will probably want to use something like this:
(key, "-----BEGIN UNSAFE PRIVATE KEY-----\n%lx\n%lx\n-----END UNSAFE PRIVATE KEY-----\n", &n, &e); fscanf
Tester Show
- I am providing the following Containerfile, which will serve as a minimal autograder.
- Use the tester with caution outside of containers as it deletes files you may want to preserve
Containerfile
FROM ubuntu
RUN apt update && apt install gcc curl python3 -y
COPY keygen.c .
COPY rsainc.c .
RUN curl https://raw.githubusercontent.com/cd-c89/crypto/refs/heads/main/rsainc/tester.py -o tester.py
Usage
- I built my container via:
podman build -t tester .
- I tested my code via:
podman run tester python3 tester.py
- If the above script returns the following you are done:
- Upload your code to your GitHub on which I am a collaborator.
- I will review the most recent version prior to the due date.
A+
A+
A+
A+
A+
A+
A+ A+
Sketch
- We note the tester performs no error handling, for which you as the student are responsible.
- This assignment was essentially as follows:
- Create a
keygen.c
that compiles into akeygen
executable with is functionally identical topython3 keygen.py
- Key generation should create an
unsafe.bad
private key and anunsafe.pub
public key.
- Key generation should create an
- Create a
rsainc.c
that compiles into arsainc
executable with is functionally identical topython3 rsa_py.py
- Encryption and decryption will use a created
unsafe.bad
private key and anunsafe.pub
public key.
- Encryption and decryption will use a created
- Create a
Tester
- The tester:
- Ensures the local directory contains no prior message, key, or executable files.
- Uses
curl
to fetch the latestkeygen.py
andrsa_py.py
from the instructional GitHub - Compiles
keygen.c
andrsainc.c
will all flags:
gcc keygen.c --std=c89 -Wall -Wextra -Werror -Wpedantic -O2 -o keygen gcc rsainc.c --std=c89 -Wall -Wextra -Werror -Wpedantic -O2 -o rsainc
- Creates a short message file containing at most two characters.
- Tests RSA for all permutations of C and Python for each stage:
- Generates keys
- Encrypts the message, and
- Decrypts the message, then
- Prints the output.