| CSE306 | Processing Systems and Structures | Lockwood, Spring 2003 |
| Purpose | User I/O, Modulo Arithmetic, Encryption algorithms |
| Points | 100 [50 * 2] |
| Due Date | Wednesday, March 12, 2003 (First 50 points) Wednesday, March 19, 2003 (Last 50 points) |
The two keys describe a function and it's inverse. That is for a public key, with a function P() and a secret key with a function S(). So, for a message M, P(S(M)) = M, and S(P(M)) = M. This is in contrast to private key cryptosystems in which there is only one function which is it's own inverse. Under private key encryption, for a private key with a function P() and a message M, P(P(M)) = M. Since it is possible to decrypt and encrypt a message with the same key, under private key encryption, it is necessary to keep the encryption key private.
RSA encryption, which stands for RSA stands for Ron Rivest, Adi Shamir and Leonard Adelman, is one of the most common methods of encrypting data today. Many algorithms use RSA as a basis for their encryption. PGP for example uses RSA to encrypt an IDEA key which is sent with the IDEA-encrypted message. Only with the correct RSA private key can you decrypt the IDEA key to decrypt the message.
In this MP, we will write an interactive assembly program that encodes and decodes text messages using RSA.
where (e, n) make up the public key. Decryption is accomplished
by the inverse operation:
T = C^d mod n
where (d, n) make up the secret key.
It should be noted that for a modulus n, you can only encode a block of text (T) that is less than n, which will produce a block of encrypted text (C) which is also less than n. For that reason, in this MP, we will be encoding 7-bit clean ASCII using a modulus > 127. The 8 bit codes can then be decrypted back into 7-bit clean ASCII.
To determine an RSA key pair, the following steps need to be followed:
1. Choose two prime numbers
p and q.
2. Multiply p*q to obtain
n.
3. Choose an encryption
key (e) which is less than {(p-1)(q-1)} and relatively prime* to {(p-1)(q-1)}.
4. Determine a decryption
key (d) such that d*e % {(p-1)(q-1)} = 1.
* Two numbers are relatively prime if they share no common
factors. In other words, the greatest common factor of two relatively
prime numbers is 1.
The public key (e, n) can now be given out freely, because it can only be used to encrypt a message. Determining the secret key from the public key (or breaking the code) is only as difficult as factoring n into it's two prime factors. For our version of RSA encryption, we are imposing the limit that n must be 8 bits long. However, RSA encryption typically uses keys that are 512, 768 or 1024 bits long.
Rather than generating random prime numbers for the key, the user can enter p, q and e. Then n and d will be calculated by the computer. This implementation is limited to encoding and decoding a single 20 byte buffer. Each byte will be encrypted and decrypted individually. The user can either enter hex values or ASCII text into the buffer to be encrypted or decrypted.
Some algorithms are described below to help you program your mp.
Let s = 1. For k = w-1 to 0: If (bit k of x) is 1 then Let R = (s · y) mod n Else Let R = s Let s = R2 mod n Return (R)(From: http://www.cryptography.com/timingattack/ )
Please note that this operation runs from the most significant bit of the exponent to the least significant bit of the exponent. This allows exponentiation to be done in a loop relative to the length of the exponent. So, for an 200 bit exponent, only 200 iterations need to be done, not 2^200.
Let f(a, b, c) be a function such that
f(a, b, c)*a mod b = c.
For simplicity, let f(a, b, c) = x0 where x0 is an integer
Note that the definition of A mod B = C states that
(x * B) + C = A
where A, B, and C are constants and x is some integer.
The Original Equation. Note that c < a
(1) (x0 * a) mod b = c
By the defintion of the modulus:
(2) (x1 * b) + c = (x0 * a) , Where x1 is some integer.
Subtract c from both sides
(3) (x1 * b) = (x0 * a) + (-c)
Taking both sides of the equation mod a:
(4a) (x1 * b) mod a = ((x0 * a) + (-c)) mod a
Since a is a factor of (x0 * a)
(4b) (x1 * b) mod a = (-c) mod a
Note that this step is the inverse of how
(2) was derived from (1).
By the property (A*B) mod C = (A*(B mod C)) mod C
(5) (x1 * (b mod a)) mod a = (-c) mod a
Note that (b mod a) and ((-c) mod a) are both constants defined
in terms of the inputs to the function a, b, and c. So, let:
b mod a = e
(-c) mod a = f
Performing this substitution gives:
(6) (x1 * e) mod a = f
Noting that this is exactly in the form of (1), we can solve for x1:
(7a) x1 = f(e, a, f)
Performing the back substitutions
(7b) x1 = f(b mod a, a, -c mod a)
Combining (7b) with (2):
(8a) (x0 * a) = f(b mod a, a, -c mod a) * b + c
and using the definition x0 = f(a,b,c)
(8b) (f(a,b,c) * a) = f(b mod a, a, -c mod a) * b + c
Dividing through by a we get:
(9) f(a, b, c) = (b*f(b mod a, a, -c mod a) + c)/a
Note that (b mod a) < a < b, and c < a.
This suggests that the recursion will shrink down to
some base case, or a set of base cases.
It is also possible that f(a, b, c) is undefined
if a = 0 (division by 0). To see what it means if f(a,b,c)
is undefined, we will work the recursion backwards.
After the nth iteration
a(n) = 0
Therefore
b(n-1) mod a(n-1) = 0
This implies that a(n-1) is a factor of b(n-1), however
b(n-1) = a(n-2)
So, a(n-1) is also a factor of a(n-2)
Also,
a(n-1) = b(n-2) mod a(n-2)
Now, taking both sides mod a(n-1)
a(n-1) mod a(n-1) = (b(n-2) mod a(n-2)) mod a(n-1)
Since A mod A = 0:
0 = (b(n-2) mod a(n-2)) mod a(n-1)
Using the definition of the modulus twice:
x1 * a(n-1) = b(n-2) mod a(n-2) , Where x1 is an integer
(x1 * a(n-1)) = b(n-2) - x2 * a(n-2) , Where x2 is an integer
But, since a(n-1) is a factor of a(n-2)
(x1 * a(n-1)) = b(n-2) - x2 * x3 * a(n-1) , Where x3 is an integer
Letting x2 absorb x3 since both are arbitrary integers:
(x1 * a(n-1) = b(n-2) - x2 * a(n-1)
Adding x2 * a(n-1) and distributing the a(n-1)
a(n-1)(x1 + x2) = b(n-2)
Letting x1 absorb x2 since both are arbitrary integers:
a(n-1)*x1 = b(n-2)
Therefore, a(n-1) is a factor of b(n-2). It was already shown
that a(n-1) is a factor of a(n-2). By induction, a(n-1) is a
factor of a(k) and b(k) where k < n and a(n) = 0. Actually, with a
slight modification to the proof, it could be shown that a(n-1) is the
greatest common factor of a(k) and b(k) for k < n.
|
T Enter text for the buffer CSE306 IS GREAT H Here is the buffer in HEX 43 53 45 33 30 36 20 49 53 20 47 52 45 41 54 E Encrypting the buffer... H Here is the buffer in HEX 21 34 54 79 66 8B 8F 7F 34 8F 33 4E 54 8C 59 D Decrypting the buffer... H Here is the buffer in HEX 43 53 45 33 30 36 20 49 53 20 47 52 45 41 54 A Here is the buffer in ASCII CSE306 IS GREAT Q |
Generating new public keys... Please enter a prime number (p): p <= 127: 7 Please enter a prime number (q): 18 < q <= 36: 19 Please enter a key (e) that is less than and relatively prime to 108: 5 The public key (e, n) is (5, 133). The private key (d, n) is (65, 133). Q |
Reading private key information... Please enter the modulus (n = p * q : n>128, n<255): 133 Please enter a public key (e): 5 The public key (e, n) is (5, 133). T Enter text for the buffer 306 H Here is the buffer in HEX 33 30 36 E Encrypting the buffer... H Here is the buffer in HEX 6D 29 50 Q |
Generating new public keys... Please enter a prime number (p): p <= 127: 7 Please enter a prime number (q): 18 < q <= 36: 19 Please enter a key (e) that is less than and relatively prime to 108: 5 The public key (e, n) is (5, 133). The private key (d, n) is (65, 133). C Enter hex for the buffer 4F 7D 1B 6D 29 50 D Decrypting the buffer... A Here is the buffer in ASCII CSE306 Q |
TITLE CSE306:MP2-RSA - Your Name - Feb 2003
; RSA Data Encryption.
;
; Interactive program which uses
; RSA encryption to encrypt and decrypt textual data.
;
; CSE306: Machine Problem 2
; Prof. John W. Lockwood
; Co-Author: Brandon Tipp
; Washington University
; Dept. of Computer Science and Engineering
; Spring 2003
;
; Ver 2.0
;====== Constants =========================================================
BEEP EQU 7
BS EQU 8
CR EQU 13
LF EQU 10
ESCKEY EQU 27
SPACE EQU 32
BufferMaxLength EQU 20 ; Bytes ; Limit text messages to one line
; when displaying message in HEX
ASCII EQU 0
HEX EQU 1
DECIMAL EQU 2
PUBLIC BEEP, BS, CR, LF, ESCKEY, SPACE, ASCII, HEX, DECIMAL, BufferMaxLength
;====== Externals =========================================================
; -- LIB306 Routines (Use Freely. Same as those used in MP1) ---
extrn kbdine:near, kbdin:near, dspout:near
extrn dspmsg:near, binasc:near, ascbin:near
extrn mp2xit:near ; Exit program with a call to this procedure
; You are GIVEN the following routines in LIB306.LIB
; (You may find these subroutines useful for your program!)
extrn kbdine:near ; From lib306
; Reads a character from standard input and saves
; the ASCII code of that register into register AL.
; The character is echoed to standard output.
extrn kbdin:near
; Same as kbdine, but without the echo (input stored in AL)
extrn binasc:near
; Converts a 16 bit binary integer into a string of decimal
; characters (ASCII-coded digits), writing them as a byte
; string into memory.
; Call with:
; AX = The 16-bit, signed integer to be converted.
; BX = Starting offset address for a 7-byte buffer to
; hold result
; (Typically the address of a variable like 'pbuf')
; Exits with:
; BX = The offset address of the first non-blank character
; of the string (this may be a minus sign, if the
; input number was negative). The string will be
; right-justified within the 7-byte buffer
; (padded with blanks to the left), and will
; have a "$" delimiter character after the last
; digit.
; CL = Number of non-blank characters generated in the
; string (including sign if number is negative).
; Example: CL = 2 for the number 78.
; Example: CL = 3 for the number -78,
extrn ascbin:near
; Converts an ASCII string in memory to 16-bit integer
; Call with:
; BX = Starting offset address for a 7-byte buffer
; holding input string, terminated with '$'
; (Typically the address of a variable like 'pbuf')
; Exits with:
; AX = Signed 16-bit integer having value of the string
; BX = Offset address of first non-convertible character
; in the string (typically ignore this field)
; DL = Error Code
; 0=No Error
; 1=String had no valid digits
; 2=String had too many digits
; 3=Overflow
; 4=Underflow (too negative)
extrn dspout:near ; From lib306
; Prints to display screen the ASCII-coded character in DL.
; Call with:
; DL = ASCII code of character to be typed on the display.
extrn dspmsg:near ; From lib306
; Prints a string of ASCII-coded characters on the display
; screen.
; String must be terminated by an ASCII dollar sign ("$").
; The starting offset of the string is to be given as an
; input in DX.
; Call with:
; DX = Offset address of first byte of the ASCII string
; to be typed
extrn mp2xit:near ; From lib306
; Exit your program
; -- LIBMP2 Routines (Replace these with your own code) ---
extrn LibPrintBuffer:near ; Print contents of Buffer
extrn LibReadBuffer:near ; Read Buffer from keyboard
extrn LibCodeBuffer:near ; Encode or decode the buffer
extrn LibExpModN:near ; Calculate X^Y mod Z
extrn LibCheckPrime:near ; Determine if a number is prime
extrn LibReadKeys:near ; Read and verify valid values for p, q, e, d
extrn LibReadPublicKeys:near ; Read in d, n
extrn LibGetD:near ; Calculate d so that a*d mod b=c
PUBLIC PrintBuffer ; Allow library to call routines
PUBLIC ReadBuffer
PUBLIC CodeBuffer
PUBLIC ExpModN
PUBLIC CheckPrime
PUBLIC ReadKeys
PUBLIC ReadPublicKeys
PUBLIC GetD
;====== SECTION 3: Define stack segment ===================================
stkseg segment stack ; *** STACK SEGMENT ***
db 64 dup ('STACK ') ; 64*8 = 512 Bytes of Stack
stkseg ends
;====== SECTION 4: Define code segment ====================================
cseg segment public 'CODE' ; *** CODE SEGMENT ***
assume cs:cseg, ds:cseg, ss:stkseg, es:nothing
;====== SECTION 5: Variables ==============================================
Buffer db BufferMaxLength dup(0) ; Data Buffer for message
BufferLength db 0 ; Number of bytes in buffer
crlf db CR,LF,'$' ; DOS uses carriage return + Linefeed for new line
PBuf db 7 dup(?)
Pmsg db 'Plese enter a prime number (p): p <= 127: ','$'
Perr1 db BEEP,'One is not prime!',CR,LF,'$'
Perr2 db BEEP,'P must be less than or equal to 127!',CR,LF,'$'
Perr3 db BEEP,'P must be a prime number!',CR,LF,'$'
Qmsg1 db 'Plese enter a prime number (q): ','$'
Qmsg2 db ' < q <= ','$'
Qerr1 db BEEP,'Q must be greater than ','$'
Qerr2 db BEEP,'Q must be less than or equal to ','$'
Qerr3 db BEEP,'Q must be a prime number!',CR,LF,'$'
PUBmsg db 'Please enter a public key (e): ',CR,LF,'$'
Nmsg db 'Please enter the modulus (n = p * q : n>128, n<255): ',CR,LF,'$'
Emsg db 'Please enter a key (e) that is less than and relatively prime to ','$'
Eerr1 db BEEP,'E must be less than ','$'
Eerr2 db BEEP,'E must be relatively prime to ','$'
Derr db BEEP,'It is insecure for D and E to be the same!',CR,LF,'$'
PubKeyMsg db 'The public key (e, n) is (','$'
PriKeyMsg db 'The private key (d, n) is (','$'
Prompt db ': ','$'
TextMsg db 'Enter text for the buffer',CR,LF,'$'
HexMsg db 'Enter hex for the buffer',CR,LF,'$'
KeyMsg db 'Generating new public keys...',CR,LF,'$'
PKeyMsg db 'Reading private key information...',CR,LF,'$'
DAscMsg db 'Here is the buffer in ASCII',CR,LF,'$'
DHexMsg db 'Here is the buffer in HEX',CR,LF,'$'
EncMsg db 'Encrypting the buffer...',CR,LF,'$'
DecMsg db 'Decrypting the buffer...',CR,LF,'$'
PUBLIC Pmsg, Perr1, Perr2, Perr3, Qmsg1, Qmsg2, Qerr1, Qerr2, Qerr3
PUBLIC Emsg, Eerr1, Eerr2, Derr, PubKeyMsg, PriKeyMsg, Prompt, crlf, PBuf
PUBLIC PUBmsg, Nmsg
p db 5 ; a prime number
q db 29 ; another prime number
n db 145 ; modulus (p * q)
e db 3 ; default encryption key [relatively prime to (p-1)*(q-1)]
d db 75 ; default decryption key [relatively prime to (p-1)*(q-1)]
; Note that keys are initialized with a valid encoding/decoding values.
; They can be changed while running the program
PUBLIC Buffer, BufferLength, e, d, p, q, n
;====== Procedures ========================================================
; Your Subroutines go here !
; ---- ----------- -- ----
PrintBuffer Proc near ; Print contents of Buffer
Call LibPrintBuffer ; Replace with your own code!
ret
PrintBuffer ENDP
ReadBuffer Proc near ; Read Buffer from keyboard
Call LibReadBuffer ; Replace with your own code!
ret
ReadBuffer ENDP
CodeBuffer Proc near ; Encode or decode the buffer
Call LibCodeBuffer ; Replace with your own code!
ret
CodeBuffer ENDP
ExpModN Proc near ; Calculate X^Y mod Z
Call LibExpModN ; Replace with your own code!
ret
ExpModN ENDP
CheckPrime Proc near ; Determine if a number is prime
Call LibCheckPrime ; Replace with your own code!
ret
CheckPrime ENDP
ReadKeys Proc near ; Read and verify valid values for p, q, e, d
Call LibReadKeys ; Replace with your own code!
ret
ReadKeys ENDP
ReadPublicKeys Proc near ; Read in d, n
Call LibReadPublicKeys ; Replace with your own code!
ret
ReadPublicKeys ENDP
GetD Proc near ; Calculate d so that a*d mod b=c
Call LibGetD ; Replace with your own code!
ret
GetD ENDP
;====== Main procedure ====================================================
MenuMessage db CR,LF
db '----------------------- MP2 Menu ---------------------',CR,LF
db ' enter: (T)ext message (C)oded hex message',CR,LF
db ' display: (A)SCII message (H)ex encoding',CR,LF
db ' generate: (K)eys (P)ublic key',CR,LF
db ' coding: (E)ncrypt (D)ecrypt',CR,LF
db '--------- [ESC] = (Q)uit -- redisplay (M)enu ---------',CR,LF,'$'
MPrompt db '>$'
main proc far
mov ax, cseg
mov ds, ax
MOV DX, Offset MenuMessage
CALL DSPMSG ; Display Menu
MainLoop: MOV DX, Offset CRLF
CALL DSPMSG
MOV DX, Offset MPrompt
CALL DSPMSG
MainRead: CALL KBDIN ; Read Input
CMP AL,'a'
JB MainOpt
CMP AL,'z' ; Convert Lowercase to Uppercase
JA MainOpt
SUB AL,'a'-'A'
MainOpt: CMP AL,'K'
JNE MainNotK
MOV DX, offset KeyMsg
CALL DSPMSG
CALL ReadKeys ; Generate a new key
JMP MainLoop
MainNotK: CMP AL,'P'
JNE MainNotP
MOV DX, offset PKeyMsg
CALL DSPMSG
CALL ReadPublicKeys ; Read in a public key
JMP MainLoop
MainNotP: CMP AL,'T'
JNE MainNotT
MOV DX, offset TextMsg
CALL DSPMSG
MOV AL, BufferMaxLength ; Read in a text message
MOV AH, ASCII
MOV BX, Offset Buffer
CALL ReadBuffer
MOV DX, Offset crlf
CALL DSPMSG
JMP MainLoop
MainNotT: CMP AL,'C'
JNE MainNotC
MOV DX, offset HexMsg
CALL DSPMSG
MOV AL, BufferMaxLength ; Read in a hex message
MOV AH, HEX
MOV BX, Offset Buffer
CALL ReadBuffer
JMP MainLoop
MainNotC: CMP AL,'E'
JNE MainNotE
MOV DX, offset EncMsg
CALL DSPMSG
MOV DH, byte ptr e ; Encode the message
MOV CL, BufferLength
MOV BX, offset Buffer
CALL CodeBuffer
JMP MainLoop
MainNotE: CMP AL,'D'
JNE MainNotD
MOV DX, offset DecMsg
CALL DSPMSG
MOV DH, byte ptr d ; Decode the message
MOV CL, BufferLength
MOV BX, offset Buffer
CALL CodeBuffer
JMP MainLoop
MainNotD: CMP AL,'A'
JNE MainNotA
MOV DX, offset DAscMsg
CALL DSPMSG
MOV AL, BufferLength ; Display the message in ASCII
MOV AH, ASCII
MOV BX, offset Buffer
CALL PrintBuffer
JMP MainLoop
MainNotA: CMP AL,'H'
JNE MainNotH
MOV DX, offset DHexMsg
CALL DSPMSG
MOV AL, BufferLength ; Display the message in Hex
MOV AH, HEX
MOV BX, Offset Buffer
CALL PrintBuffer
JMP MainLoop
MainNotH: CMP AL,'M'
JNE MainNotM
MOV DX, offset MenuMessage
CALL DSPMSG
JMP MainLoop
MainNotM: CMP AL,ESCKEY
JE MainDone ; Quit program
CMP AL,'Q'
JE MainDone
JMP MainRead ; Ignore any other character
MainDone: call MP2XIT ; Exit to DOS
main endp
cseg ends
end main