Update all new Tasks
This commit is contained in:
parent
00a190b0a6
commit
91df62d461
5697 changed files with 93386 additions and 804 deletions
37
Task/RSA-code/00DESCRIPTION
Normal file
37
Task/RSA-code/00DESCRIPTION
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
Given an [[wp:RSA|RSA]] key (n,e,d), construct a program to encrypt and decrypt plaintext messages strings.
|
||||
|
||||
'''Background'''
|
||||
|
||||
RSA code is used to encode secret messages. It is named after Ron Rivest, Adi Shamir, and Leonard Adleman who published it at MIT in 1977. The advantage of this type of encryption is that you can distribute the number “<math>n</math>” and “<math>e</math>” (which makes up the Public Key used for encryption) to everyone. The Private Key used for decryption “<math>d</math>” is kept secret, so that only the recipient can read the encrypted plaintext.
|
||||
|
||||
The process by which this is done is that a message, for example “Hello World” is encoded as numbers (This could be encoding as ASCII or as a subset of characters <math>a=01,b=02,...,z=26</math>). This yields a string of numbers, generally referred to as "numerical plaintext", “<math>P</math>”. For example, “Hello World” encoded with a=1,...,z=26 by hundreds would yield <math>0805 1212 1523 1518 1204</math>.
|
||||
|
||||
The plaintext must also be split into blocks so that the numerical plaintext is smaller than <math>n</math> otherwise the decryption will fail.
|
||||
|
||||
The ciphertext, <math>C</math>, is then computed by taking each block of <math>P</math>, and computing
|
||||
: <math>C \equiv P^e \mod n</math>
|
||||
Similarly, to decode, one computes
|
||||
: <math>P \equiv C^d \mod n</math>
|
||||
|
||||
To generate a key, one finds 2 (ideally large) primes <math>p</math> and <math>q</math>. the value “<math>n</math>” is simply: <math>n = p \times q</math>.
|
||||
One must then choose an “<math>e</math>” such that <math>\gcd(e, (p-1)\times(q-1) ) = 1</math>. That is to say, <math>e</math> and <math>(p-1)\times(q-1)</math> are relatively prime to each other.
|
||||
|
||||
The decryption value <math>d</math> is then found by solving
|
||||
: <math>d\times e \equiv 1 \mod (p-1)\times(q-1)</math>
|
||||
|
||||
The security of the code is based on the secrecy of the Private Key (decryption exponent) “<math>d</math>” and the difficulty in factoring “<math>n</math>”. Research into RSA facilitated advances in factoring and a number of [http://www.rsa.com/rsalabs/node.asp?id=2092 factoring challenges]. Keys of 768 bits have been successfully factored. While factoring of keys of 1024 bits has not been demonstrated, NIST expected them to be factorable by 2010 and now recommends 2048 bit keys going forward (see [[wp:Key_size#Asymmetric_algorithm_key_lengths|Asymmetric algorithm key lengths]] or [http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57-Part1-revised2_Mar08-2007.pdf NIST 800-57 Pt 1 Revised Table 4: Recommended algorithms and minimum key sizes]).
|
||||
|
||||
'''Summary of the task requirements:'''
|
||||
|
||||
* Encrypt and Decrypt a short message or two using RSA with a demonstration key.
|
||||
* Implement RSA do not call a library.
|
||||
* Encode and decode the message using any reversible method of your choice (ASCII or a=1,..,z=26 are equally fine).
|
||||
* Either support blocking or give an error if the message would require blocking)
|
||||
* Demonstrate that your solution could support real keys by using a non-trivial key that requires large integer support (built-in or libraries). There is no need to include library code but it must be referenced unless it is built into the language. The following keys will be meet this requirement;however, they are NOT long enough to be considered secure:
|
||||
:: n = 9516311845790656153499716760847001433441357
|
||||
:: e = 65537
|
||||
:: d = 5617843187844953170308463622230283376298685
|
||||
* Messages can be hard-coded into the program, there is no need for elaborate input coding.
|
||||
* Demonstrate that your implementation works by showing plaintext, intermediate results, encrypted text, and decrypted text.
|
||||
|
||||
{{alertbox|#ffff70|'''<big>Warning</big>'''<br/>Rosetta Code is '''not''' a place you should rely on for examples of code in critical roles, including security.<br/>Cryptographic routines should be validated before being used.<br/>For a discussion of limitations and please refer to [[Talk:RSA_code#Difference_from_practical_cryptographical_version]].}}
|
||||
2
Task/RSA-code/00META.yaml
Normal file
2
Task/RSA-code/00META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
note: Encryption
|
||||
32
Task/RSA-code/Common-Lisp/rsa-code.lisp
Normal file
32
Task/RSA-code/Common-Lisp/rsa-code.lisp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
(defparameter *n* 9516311845790656153499716760847001433441357)
|
||||
(defparameter *e* 65537)
|
||||
(defparameter *d* 5617843187844953170308463622230283376298685)
|
||||
|
||||
;; magic
|
||||
(defun encode-string (message)
|
||||
(parse-integer (reduce #'(lambda (x y) (concatenate 'string x y))
|
||||
(loop for c across message collect (format nil "~2,'0d" (- (char-code c) 32))))))
|
||||
|
||||
;; sorcery
|
||||
(defun decode-string (message) (coerce (loop for (a b) on
|
||||
(loop for char across (write-to-string message) collect char)
|
||||
by #'cddr collect (code-char (+ (parse-integer (coerce (list a b) 'string)) 32))) 'string))
|
||||
|
||||
;; ACTUAL RSA ALGORITHM STARTS HERE ;;
|
||||
|
||||
;; fast modular exponentiation: runs in O(log exponent)
|
||||
;; acc is initially 1 and contains the result by the end
|
||||
(defun mod-exp (base exponent modulus acc)
|
||||
(if (= exponent 0) acc
|
||||
(mod-exp (mod (* base base) modulus) (ash exponent -1) modulus
|
||||
(if (= (mod exponent 2) 1) (mod (* acc base) modulus) acc))))
|
||||
|
||||
;; to encode a message, we first convert it to its integer form.
|
||||
;; then, we raise it to the *e* power, modulo *n*
|
||||
(defun encode-rsa (message)
|
||||
(mod-exp (encode-string message) *e* *n* 1))
|
||||
|
||||
;; to decode a message, we raise it to *d* power, modulo *n*
|
||||
;; and then convert it back into a string
|
||||
(defun decode-rsa (message)
|
||||
(decode-string (mod-exp message *d* *n* 1)))
|
||||
35
Task/RSA-code/D/rsa-code.d
Normal file
35
Task/RSA-code/D/rsa-code.d
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
void main() {
|
||||
import std.stdio, std.bigint, std.algorithm, std.string, std.range,
|
||||
modular_exponentiation;
|
||||
|
||||
immutable txt = "Rosetta Code";
|
||||
writeln("Plain text: ", txt);
|
||||
|
||||
// A key set big enough to hold 16 bytes of plain text in
|
||||
// a single block (to simplify the example) and also big enough
|
||||
// to demonstrate efficiency of modular exponentiation.
|
||||
immutable BigInt n = "2463574872878749457479".BigInt *
|
||||
"3862806018422572001483".BigInt;
|
||||
immutable BigInt e = 2 ^^ 16 + 1;
|
||||
immutable BigInt d = "5617843187844953170308463622230283376298685";
|
||||
|
||||
// Convert plain text to a number.
|
||||
immutable txtN = reduce!q{ (a << 8) | uint(b) }(0.BigInt, txt);
|
||||
if (txtN >= n)
|
||||
return writeln("Plain text message too long.");
|
||||
writeln("Plain text as a number: ", txtN);
|
||||
|
||||
// Encode a single number.
|
||||
immutable enc = txtN.powMod(e, n);
|
||||
writeln("Encoded: ", enc);
|
||||
|
||||
// Decode a single number.
|
||||
auto dec = enc.powMod(d, n);
|
||||
writeln("Decoded: ", dec);
|
||||
|
||||
// Convert number to text.
|
||||
char[] decTxt;
|
||||
for (; dec; dec >>= 8)
|
||||
decTxt ~= (dec & 0xff).toInt;
|
||||
writeln("Decoded number as text: ", decTxt.retro);
|
||||
}
|
||||
48
Task/RSA-code/Go/rsa-code.go
Normal file
48
Task/RSA-code/Go/rsa-code.go
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var n, e, d, bb, ptn, etn, dtn big.Int
|
||||
pt := "Rosetta Code"
|
||||
fmt.Println("Plain text: ", pt)
|
||||
|
||||
// a key set big enough to hold 16 bytes of plain text in
|
||||
// a single block (to simplify the example) and also big enough
|
||||
// to demonstrate efficiency of modular exponentiation.
|
||||
n.SetString("9516311845790656153499716760847001433441357", 10)
|
||||
e.SetString("65537", 10)
|
||||
d.SetString("5617843187844953170308463622230283376298685", 10)
|
||||
|
||||
// convert plain text to a number
|
||||
for _, b := range []byte(pt) {
|
||||
ptn.Or(ptn.Lsh(&ptn, 8), bb.SetInt64(int64(b)))
|
||||
}
|
||||
if ptn.Cmp(&n) >= 0 {
|
||||
fmt.Println("Plain text message too long")
|
||||
return
|
||||
}
|
||||
fmt.Println("Plain text as a number:", &ptn)
|
||||
|
||||
// encode a single number
|
||||
etn.Exp(&ptn, &e, &n)
|
||||
fmt.Println("Encoded: ", &etn)
|
||||
|
||||
// decode a single number
|
||||
dtn.Exp(&etn, &d, &n)
|
||||
fmt.Println("Decoded: ", &dtn)
|
||||
|
||||
// convert number to text
|
||||
var db [16]byte
|
||||
dx := 16
|
||||
bff := big.NewInt(0xff)
|
||||
for dtn.BitLen() > 0 {
|
||||
dx--
|
||||
db[dx] = byte(bb.And(&dtn, bff).Int64())
|
||||
dtn.Rsh(&dtn, 8)
|
||||
}
|
||||
fmt.Println("Decoded number as text:", string(db[dx:]))
|
||||
}
|
||||
65
Task/RSA-code/Icon/rsa-code.icon
Normal file
65
Task/RSA-code/Icon/rsa-code.icon
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
procedure main() # rsa demonstration
|
||||
|
||||
n := 9516311845790656153499716760847001433441357
|
||||
e := 65537
|
||||
d := 5617843187844953170308463622230283376298685
|
||||
b := 2^integer(log(n,2)) # for blocking
|
||||
write("RSA Demo using\n n = ",n,"\n e = ",e,"\n d = ",d,"\n b = ",b)
|
||||
|
||||
every m := !["Rosetta Code", "Hello Word!",
|
||||
"This message is too long.", repl("x",*decode(n+1))] do {
|
||||
write("\nMessage = ",image(m))
|
||||
write( "Encoded = ",m := encode(m))
|
||||
if m := rsa(m,e,n) then { # unblocked
|
||||
write( "Encrypt = ",m)
|
||||
write( "Decrypt = ",m := rsa(m,d,n))
|
||||
}
|
||||
else { # blocked
|
||||
every put(C := [], rsa(!block(m,b),e,n))
|
||||
writes("Encrypt = ") ; every writes(!C," ") ; write()
|
||||
every put(P := [], rsa(!C,d,n))
|
||||
writes("Decrypt = ") ; every writes(!P," ") ; write()
|
||||
write("Unblocked = ",m := unblock(P,b))
|
||||
}
|
||||
write( "Decoded = ",image(decode(m)))
|
||||
}
|
||||
end
|
||||
|
||||
procedure mod_power(base, exponent, modulus) # fast modular exponentation
|
||||
result := 1
|
||||
while exponent > 0 do {
|
||||
if exponent % 2 = 1 then
|
||||
result := (result * base) % modulus
|
||||
exponent /:= 2
|
||||
base := base ^ 2 % modulus
|
||||
}
|
||||
return result
|
||||
end
|
||||
|
||||
procedure rsa(text,e,n) # return rsa encryption of numerically encoded message; fail if text < n
|
||||
return mod_power(text,e,text < n)
|
||||
end
|
||||
|
||||
procedure encode(text) # numerically encode ascii text as int
|
||||
every (message := 0) := ord(!text) + 256 * message
|
||||
return message
|
||||
end
|
||||
|
||||
procedure decode(message) # numerically decode int to ascii text
|
||||
text := ""
|
||||
while text ||:= char((0 < message) % 256) do
|
||||
message /:= 256
|
||||
return reverse(text)
|
||||
end
|
||||
|
||||
procedure block(m,b) # break lg int into blocks of size b
|
||||
M := []
|
||||
while push(M, x := (0 < m) % b) do
|
||||
m /:= b
|
||||
return M
|
||||
end
|
||||
|
||||
procedure unblock(M,b) # reassemble blocks of size b into lg int
|
||||
every (m := 0) := !M + b * m
|
||||
return m
|
||||
end
|
||||
16
Task/RSA-code/J/rsa-code.j
Normal file
16
Task/RSA-code/J/rsa-code.j
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
N=: 9516311845790656153499716760847001433441357x
|
||||
E=: 65537x
|
||||
D=: 5617843187844953170308463622230283376298685x
|
||||
|
||||
] text=: 'Rosetta Code'
|
||||
Rosetta Code
|
||||
] num=: 256x #. a.i.text
|
||||
25512506514985639724585018469
|
||||
num >: N NB. check if blocking is necessary (0 means no)
|
||||
0
|
||||
] enc=: N&|@^&E num
|
||||
916709442744356653386978770799029131264344
|
||||
] dec=: N&|@^&D enc
|
||||
25512506514985639724585018469
|
||||
] final=: a. {~ 256x #.inv dec
|
||||
Rosetta Code
|
||||
44
Task/RSA-code/Perl-6/rsa-code.pl6
Normal file
44
Task/RSA-code/Perl-6/rsa-code.pl6
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
constant $n = 9516311845790656153499716760847001433441357;
|
||||
constant $e = 65537;
|
||||
constant $d = 5617843187844953170308463622230283376298685;
|
||||
|
||||
my $secret-message = "ROSETTA CODE";
|
||||
|
||||
package Message {
|
||||
my @alphabet = 'A' .. 'Z', ' ';
|
||||
my $rad = +@alphabet;
|
||||
my %code = @alphabet Z=> 0 .. *;
|
||||
subset Text of Str where /^^ @alphabet+ $$/;
|
||||
our sub encode(Text $t) {
|
||||
[+] %code{$t.flip.comb} Z* (1, $rad, $rad*$rad ... *);
|
||||
}
|
||||
our sub decode(Int $n is copy) {
|
||||
@alphabet[
|
||||
gather loop {
|
||||
take $n % $rad;
|
||||
last if $n < $rad;
|
||||
$n div= $rad;
|
||||
}
|
||||
].join.flip;
|
||||
}
|
||||
}
|
||||
|
||||
use Test;
|
||||
plan 1;
|
||||
|
||||
say "Secret message is $secret-message";
|
||||
say "Secret message in integer form is $_" given
|
||||
my $numeric-message = Message::encode $secret-message;
|
||||
say "After exponentiation with public exponent we get: $_" given
|
||||
my $numeric-cipher = expmod $numeric-message, $e, $n;
|
||||
say "This turns into the string $_" given
|
||||
my $text-cipher = Message::decode $numeric-cipher;
|
||||
|
||||
say "If we re-encode it in integer form we get $_" given
|
||||
my $numeric-cipher2 = Message::encode $text-cipher;
|
||||
say "After exponentiation with SECRET exponent we get: $_" given
|
||||
my $numeric-message2 = expmod $numeric-cipher2, $d, $n;
|
||||
say "This turns into the string $_" given
|
||||
my $secret-message2 = Message::decode $numeric-message2;
|
||||
|
||||
is $secret-message, $secret-message2, "the message has been correctly decrypted";
|
||||
116
Task/RSA-code/PicoLisp/rsa-code.l
Normal file
116
Task/RSA-code/PicoLisp/rsa-code.l
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
### This is a copy of "lib/rsa.l" ###
|
||||
|
||||
# Generate long random number
|
||||
(de longRand (N)
|
||||
(use (R D)
|
||||
(while (=0 (setq R (abs (rand)))))
|
||||
(until (> R N)
|
||||
(unless (=0 (setq D (abs (rand))))
|
||||
(setq R (* R D)) ) )
|
||||
(% R N) ) )
|
||||
|
||||
# X power Y modulus N
|
||||
(de **Mod (X Y N)
|
||||
(let M 1
|
||||
(loop
|
||||
(when (bit? 1 Y)
|
||||
(setq M (% (* M X) N)) )
|
||||
(T (=0 (setq Y (>> 1 Y)))
|
||||
M )
|
||||
(setq X (% (* X X) N)) ) ) )
|
||||
|
||||
# Probabilistic prime check
|
||||
(de prime? (N)
|
||||
(and
|
||||
(> N 1)
|
||||
(bit? 1 N)
|
||||
(let (Q (dec N) K 0)
|
||||
(until (bit? 1 Q)
|
||||
(setq
|
||||
Q (>> 1 Q)
|
||||
K (inc K) ) )
|
||||
(do 50
|
||||
(NIL (_prim? N Q K))
|
||||
T ) ) ) )
|
||||
|
||||
# (Knuth Vol.2, p.379)
|
||||
(de _prim? (N Q K)
|
||||
(use (X J Y)
|
||||
(while (> 2 (setq X (longRand N))))
|
||||
(setq
|
||||
J 0
|
||||
Y (**Mod X Q N) )
|
||||
(loop
|
||||
(T
|
||||
(or
|
||||
(and (=0 J) (= 1 Y))
|
||||
(= Y (dec N)) )
|
||||
T )
|
||||
(T
|
||||
(or
|
||||
(and (> J 0) (= 1 Y))
|
||||
(<= K (inc 'J)) )
|
||||
NIL )
|
||||
(setq Y (% (* Y Y) N)) ) ) )
|
||||
|
||||
# Find a prime number with `Len' digits
|
||||
(de prime (Len)
|
||||
(let P (longRand (** 10 (*/ Len 2 3)))
|
||||
(unless (bit? 1 P)
|
||||
(inc 'P) )
|
||||
(until (prime? P) # P: Prime number of size 2/3 Len
|
||||
(inc 'P 2) )
|
||||
# R: Random number of size 1/3 Len
|
||||
(let (R (longRand (** 10 (/ Len 3))) K (+ R (% (- P R) 3)))
|
||||
(when (bit? 1 K)
|
||||
(inc 'K 3) )
|
||||
(until (prime? (setq R (inc (* K P))))
|
||||
(inc 'K 6) )
|
||||
R ) ) )
|
||||
|
||||
# Generate RSA key
|
||||
(de rsaKey (N) #> (Encrypt . Decrypt)
|
||||
(let (P (prime (*/ N 5 10)) Q (prime (*/ N 6 10)))
|
||||
(cons
|
||||
(* P Q)
|
||||
(/
|
||||
(inc (* 2 (dec P) (dec Q)))
|
||||
3 ) ) ) )
|
||||
|
||||
# Encrypt a list of characters
|
||||
(de encrypt (Key Lst)
|
||||
(let Siz (>> 1 (size Key))
|
||||
(make
|
||||
(while Lst
|
||||
(let N (char (pop 'Lst))
|
||||
(while (> Siz (size N))
|
||||
(setq N (>> -16 N))
|
||||
(inc 'N (char (pop 'Lst))) )
|
||||
(link (**Mod N 3 Key)) ) ) ) ) )
|
||||
|
||||
# Decrypt a list of numbers
|
||||
(de decrypt (Keys Lst)
|
||||
(mapcan
|
||||
'((N)
|
||||
(let Res NIL
|
||||
(setq N (**Mod N (cdr Keys) (car Keys)))
|
||||
(until (=0 N)
|
||||
(push 'Res (char (& `(dec (** 2 16)) N)))
|
||||
(setq N (>> 16 N)) )
|
||||
Res ) )
|
||||
Lst ) )
|
||||
### End of "lib/rsa.l" ###
|
||||
|
||||
# Generate 100-digit keys (private . public)
|
||||
: (setq Keys (rsaKey 100))
|
||||
-> (14394597526321726957429995133376978449624406217727317004742182671030....
|
||||
|
||||
# Encrypt
|
||||
: (setq CryptText
|
||||
(encrypt (car Keys)
|
||||
(chop "The quick brown fox jumped over the lazy dog's back") ) )
|
||||
-> (72521958974980041245760752728037044798830723189142175108602418861716...
|
||||
|
||||
# Decrypt
|
||||
: (pack (decrypt Keys CryptText))
|
||||
-> "The quick brown fox jumped over the lazy dog's back"
|
||||
222
Task/RSA-code/Python/rsa-code-1.py
Normal file
222
Task/RSA-code/Python/rsa-code-1.py
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
from tkinter import *
|
||||
import random
|
||||
import time
|
||||
|
||||
letter = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q",
|
||||
"r","s","t","u","v","w","x","y","z",",",".","!","?",' ']
|
||||
number = ["01","02","03","04","05","06","07","08","09","10","11","12","13",
|
||||
"14","15","16","17","18","19","20","21","22","23","24","25","26","27",
|
||||
"28","29","30",'31']
|
||||
|
||||
n = 2537
|
||||
e = 13
|
||||
d = 937
|
||||
def decrypt(F,d):
|
||||
# performs the decryption function on an block of ciphertext
|
||||
if d == 0:
|
||||
return 1
|
||||
if d == 1:
|
||||
return F
|
||||
w,r = divmod(d,2)
|
||||
if r == 1:
|
||||
return decrypt(F*F%n,w)*F%n
|
||||
else:
|
||||
return decrypt(F*F%n,w)
|
||||
|
||||
def correct():
|
||||
# Checks to see if the numerical ciphertext block should have started with a 0 (by seeing if the 0 is missing), if it is, it then adds the 0.
|
||||
# example - 0102 is output as 102, which would lead the computer to think the first letter is 10, not 01. This ensures this does not happen.
|
||||
for i in range(len(D)):
|
||||
if len(str(P[i]))%2 !=0:
|
||||
y = str(0)+str(P[i])
|
||||
P.remove(str(P[i]))
|
||||
P.insert(i,y)
|
||||
|
||||
def cipher(b,e):
|
||||
# Performs the Encryption function on a block of ciphertext
|
||||
if e == 0:
|
||||
return 1
|
||||
if e == 1:
|
||||
return b
|
||||
w,r = divmod(e,2)
|
||||
if r == 1:
|
||||
return cipher(b*b%n,w)*b%n
|
||||
else:
|
||||
return cipher(b*b%n,w)
|
||||
|
||||
def group(j,h,z):
|
||||
# Places the plaintext numbers into blocks for encryption
|
||||
for i in range(int(j)):
|
||||
y = 0
|
||||
for n in range(h):
|
||||
y += int(numP[(h*i)+n])*(10**(z-2*n))
|
||||
X.append(int(y))
|
||||
|
||||
|
||||
|
||||
class App:
|
||||
# Creates a Tkineter window, for ease of operation
|
||||
def __init__(self, master):
|
||||
|
||||
frame = Frame(master)
|
||||
frame.grid()
|
||||
|
||||
#create a button with the quit command, and tell it where to go
|
||||
quitbutton = Button(frame, text = "quit", fg ="red",
|
||||
command = root.quit, width = 10)
|
||||
quitbutton.grid(row = 0, column =3)
|
||||
|
||||
#create an entry box, tell it where it goes, and how large it is
|
||||
entry = Entry(frame, width = 100)
|
||||
entry.grid(row = 0, column = 0)
|
||||
|
||||
#set initial content of the entry box
|
||||
self.contents = StringVar()
|
||||
self.contents.set("Type message here")
|
||||
entry["textvariable"] = self.contents
|
||||
|
||||
# Create a button which initializes the decryption of ciphertext
|
||||
decrypt = Button(frame,text = "Decrypt", fg = "blue",
|
||||
command = self.Decrypt)
|
||||
decrypt.grid(row = 2, column = 1)
|
||||
|
||||
#create a label to display the number of ciphertext blocks in an encoded message
|
||||
label = Label(frame, text = "# of blocks")
|
||||
label.grid(row = 1, column = 1)
|
||||
|
||||
#creates a button which initializes the encryption of plaintext
|
||||
encrypt = Button(frame, text="Encrypt", fg = "blue",
|
||||
command = self.Encrypt)
|
||||
encrypt.grid(row =0, column =1)
|
||||
|
||||
#create an entry box for the value of "n"
|
||||
nbox = Entry(frame, width = 100)
|
||||
nbox.grid(row = 3, column = 0)
|
||||
|
||||
self.n = StringVar()
|
||||
self.n.set(n)
|
||||
nbox["textvar"] = self.n
|
||||
nbox.bind('<Key-Return>', self.set_n) #key binding, when you press "return", the value of "n" is changed to the value now in the box
|
||||
|
||||
nlabel = Label(frame, text = "the value of 'n'")
|
||||
nlabel.grid(row = 3, column = 1)
|
||||
|
||||
#create an entry box for the value of "e"
|
||||
ebox = Entry(frame, width = 100)
|
||||
ebox.grid(row = 4, column = 0)
|
||||
|
||||
self.e = StringVar()
|
||||
self.e.set(e)
|
||||
ebox["textvar"] = self.e
|
||||
ebox.bind('<Key-Return>', self.set_e)
|
||||
|
||||
elabel = Label(frame, text = "the value of 'e'")
|
||||
elabel.grid(row = 4, column = 1)
|
||||
|
||||
#create an entry box for the value of "d"
|
||||
dbox = Entry(frame, width = 100)
|
||||
dbox.grid(row =5, column = 0)
|
||||
|
||||
self.d = StringVar()
|
||||
self.d.set(d)
|
||||
dbox["textvar"] = self.d
|
||||
dbox.bind('<Key-Return>', self.set_d)
|
||||
|
||||
dlabel = Label(frame, text = "the value of 'd'")
|
||||
dlabel.grid(row = 5, column =1)
|
||||
|
||||
blocks = Label(frame, width = 100)
|
||||
blocks.grid(row = 1, column =0)
|
||||
|
||||
self.block = StringVar()
|
||||
self.block.set("number of blocks")
|
||||
blocks["textvar"] = self.block
|
||||
|
||||
output = Entry(frame, width = 100)
|
||||
output.grid(row = 2, column = 0)
|
||||
|
||||
self.answer = StringVar()
|
||||
self.answer.set("Ciphertext")
|
||||
output["textvar"] = self.answer
|
||||
|
||||
# The commands of all the buttons are defined below
|
||||
def set_n(self,event):
|
||||
global n
|
||||
n = int(self.n.get())
|
||||
print("n set to", n)
|
||||
|
||||
def set_e(self, event):
|
||||
global e
|
||||
e = int(self.e.get())
|
||||
print("e set to",e)
|
||||
|
||||
def set_d(self,event):
|
||||
global d
|
||||
d = int(self.d.get())
|
||||
print("d set to", d)
|
||||
|
||||
def Decrypt(self):
|
||||
#decrypts an encoded message
|
||||
global m,P,D,x,h,p,Text,y,w,PText
|
||||
P = []
|
||||
D = str(self.answer.get()) #Pulls the ciphertext out of the ciphertext box
|
||||
D = D.lstrip('[') #removes the bracket "[" from the left side of the string
|
||||
D = D.rstrip(']')
|
||||
D = D.split(',') #splits the string into a list of strings, separating at each comma.
|
||||
for i in range(len(D)): #decrypts each block in the list of strings "D"
|
||||
x = decrypt(int(D[i]),d)
|
||||
P.append(str(x))
|
||||
correct() #ensures each block is not missing a 0 at the start
|
||||
h = len(P[0])
|
||||
p = []
|
||||
for i in range(len(D)): #further separates the list P into individual characters, i.e. "0104" becomes "01,04"
|
||||
for n in range(int(h/2)):
|
||||
p.append(str(P[i][(2*n):((2*n)+2)])) # grabs every 2 character group from the larger block. It gets characters between 2*n, and (2*n)+2, i.e. characters 0,1 then 2,3 etc...
|
||||
|
||||
Text = []
|
||||
for i in range(len(p)): # converts each block back to text characters
|
||||
for j in range(len(letter)):
|
||||
if str(p[i]) == number[j]:
|
||||
Text.append(letter[j])
|
||||
PText = str()
|
||||
for i in range(len(Text)): #places all text characters in one string
|
||||
PText = PText + str(Text[i])
|
||||
self.contents.set(str(PText)) #places the decrypted plaintext in the plaintext box
|
||||
|
||||
|
||||
def Encrypt(self):
|
||||
#encrypts a plaintext message using the current key
|
||||
global plaintext,numP,q,j,z,X,C
|
||||
plaintext = self.contents.get() #pulls the plaintext out of the entry box for use
|
||||
plaintext = plaintext.lower() #places all plaintext in lower case
|
||||
numP = []
|
||||
for i in range(len(plaintext)): # converts letters and symbols to their numerical values
|
||||
for j in range(len(letter)):
|
||||
if plaintext[i] == letter[j]:
|
||||
numP.append(number[j])
|
||||
h = (len(str(n))//2)-1 # This sets the block length for the code in question, based on the value of "n"
|
||||
q = len(numP)%h
|
||||
for i in range(h-q):
|
||||
numP.append(number[random.randint(0,25)]) # Ensures the final block of plaintext is filled with letters, and is not a single orphaned letter.
|
||||
j = len(numP) / h
|
||||
X = []
|
||||
z = 0
|
||||
for m in range(h-1):
|
||||
z+=2
|
||||
group(j,h,z) # This sets the numerical plaintext into blocks of appropriate size, and places them in the list "X"
|
||||
k = len(X)
|
||||
C = []
|
||||
for i in range(k): # performs the cipher function for each block in the list of plaintext blocks
|
||||
b = X[i]
|
||||
r = cipher(b,e)
|
||||
C.append(r)
|
||||
self.answer.set(C)
|
||||
self.block.set(len(C)) #places the ciphertext into the ciphertext box
|
||||
|
||||
|
||||
root = Tk()
|
||||
|
||||
app = App(root)
|
||||
|
||||
root.mainloop()
|
||||
root.destroy()
|
||||
186
Task/RSA-code/Python/rsa-code-2.py
Normal file
186
Task/RSA-code/Python/rsa-code-2.py
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
import random
|
||||
import time
|
||||
|
||||
def decrypt(F,d):
|
||||
if d == 0:
|
||||
return 1
|
||||
if d == 1:
|
||||
return F
|
||||
w,r = divmod(d,2)
|
||||
if r == 1:
|
||||
return decrypt(F*F%n,w)*F%n
|
||||
else:
|
||||
return decrypt(F*F%n,w)
|
||||
|
||||
def correct():
|
||||
for i in range(len(C)):
|
||||
if len(str(P[i]))%2 !=0:
|
||||
y = str(0)+str(P[i])
|
||||
P.remove(str(P[i]))
|
||||
P.insert(i,y)
|
||||
|
||||
def cipher(b,e):
|
||||
if e == 0:
|
||||
return 1
|
||||
if e == 1:
|
||||
return b
|
||||
w,r = divmod(e,2)
|
||||
if r == 1:
|
||||
return cipher(b*b%n,w)*b%n
|
||||
else:
|
||||
return cipher(b*b%n,w)
|
||||
|
||||
def group(j,h,z):
|
||||
for i in range(int(j)):
|
||||
y = 0
|
||||
for n in range(h):
|
||||
y += int(numP[(h*i)+n])*(10**(z-2*n))
|
||||
X.append(int(y))
|
||||
|
||||
def gcd(a, b):
|
||||
while b != 0:
|
||||
(a, b) = (b, a%b)
|
||||
return a
|
||||
|
||||
|
||||
|
||||
letter = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q",
|
||||
"r","s","t","u","v","w","x","y","z",",",".","!","?"," "]
|
||||
number = ["01","02","03","04","05","06","07","08","09","10","11","12","13",
|
||||
"14","15","16","17","18","19","20","21","22","23","24","25","26","27",
|
||||
"28","29","30","31"]
|
||||
|
||||
|
||||
print( '\n' )
|
||||
def Decrypt():
|
||||
#decrypts an encoded message
|
||||
global m,P,C,x,h,p,Text,y,w
|
||||
P = []
|
||||
C = str(input("Enter ciphertext blocks:"))
|
||||
C = C.lstrip('[')
|
||||
C = C.rstrip(']')
|
||||
C = C.split(',')
|
||||
for i in range(len(C)):
|
||||
x = decrypt(int(C[i]),d)
|
||||
P.append(str(x))
|
||||
correct()
|
||||
#print(P)
|
||||
h = len(P[0])
|
||||
p = []
|
||||
for i in range(len(C)):
|
||||
for n in range(int(h/2)):
|
||||
p.append(str(P[i][(2*n):((2*n)+2)]))
|
||||
|
||||
Text = []
|
||||
for i in range(len(p)):
|
||||
for j in range(len(letter)):
|
||||
if str(p[i]) == number[j]:
|
||||
Text.append(letter[j])
|
||||
PText = str()
|
||||
for i in range(len(Text)):
|
||||
PText = PText + str(Text[i])
|
||||
print("Plaintext is:", PText)
|
||||
|
||||
def Encrypt():
|
||||
#encrypts a plaintext message using the current key
|
||||
global plaintext,numP,q,j,z,X,C
|
||||
plaintext =(input("Enter Plaintext :"))
|
||||
plaintext = plaintext.lower()
|
||||
numP = []
|
||||
for i in range(len(plaintext)):
|
||||
for j in range(len(letter)):
|
||||
if plaintext[i] == letter[j]:
|
||||
numP.append(number[j])
|
||||
h = (len(str(n))//2)-1
|
||||
q = len(numP)%h
|
||||
for i in range(h-q):
|
||||
numP.append(number[random.randint(0,25)])
|
||||
j = len(numP) / h
|
||||
#print(numP)
|
||||
X = []
|
||||
z = 0
|
||||
for m in range(h-1):
|
||||
z+=2
|
||||
group(j,h,z)
|
||||
k = len(X)
|
||||
C = []
|
||||
for i in range(k):
|
||||
b = X[i]
|
||||
r = cipher(b,e)
|
||||
C.append(r)
|
||||
print("Ciphertext:",C)
|
||||
print("Number of Ciphertext blocks:",len(C))
|
||||
|
||||
def setup():
|
||||
global n,e,d
|
||||
while True:
|
||||
try:
|
||||
n = int(input(" Enter a value for n :"))
|
||||
if n > 2:
|
||||
break
|
||||
except ValueError:
|
||||
print('please enter a number')
|
||||
while 1!=2 :
|
||||
try:
|
||||
e = int(input(" Enter a value for e :"))
|
||||
if e >= 2:
|
||||
break
|
||||
except ValueError:
|
||||
print('please enter a number')
|
||||
while True:
|
||||
try:
|
||||
d = int(input(" Enter a value for d. If d unknown, enter 0 :"))
|
||||
if d >= 0:
|
||||
break
|
||||
except ValueError:
|
||||
print('please enter a number')
|
||||
|
||||
#setup()
|
||||
n = 2537
|
||||
e = 13
|
||||
d = 937
|
||||
|
||||
print("To redefine n,e, or d, type 'n','e',... etc.")
|
||||
print("To encrypt a message with the current key, type 'Encrypt'")
|
||||
print("To decrypt a message with the current key, type 'Decrypt'")
|
||||
print("Type quit to exit")
|
||||
print( '\n' )
|
||||
print( '\n' )
|
||||
|
||||
mm = str()
|
||||
while mm != 'quit':
|
||||
mm = input("Enter Command...")
|
||||
if mm.lower() == 'encrypt':
|
||||
Encrypt()
|
||||
elif mm.lower() == 'decrypt':
|
||||
Decrypt()
|
||||
elif mm.lower() == 'n':
|
||||
try:
|
||||
print('current n = ',n)
|
||||
n = int(input(" Enter a value for n :"))
|
||||
except ValueError:
|
||||
print('That is not a valid entry')
|
||||
elif mm.lower() == 'help':
|
||||
print("To redefine n,e, or d, type 'n','e',... etc.")
|
||||
print("To encrypt a message with the current key, type 'Encrypt'")
|
||||
print("To decrypt a message with the current key, type 'Decrypt'")
|
||||
print("Type quit to exit")
|
||||
print( '\n' )
|
||||
print( '\n' )
|
||||
elif mm.lower() == 'e':
|
||||
try:
|
||||
print('current e = ',e)
|
||||
e = int(input(" Enter a value for e :"))
|
||||
except ValueError:
|
||||
print('That is not a valid entry')
|
||||
elif mm.lower() == 'd':
|
||||
try:
|
||||
print('current d = ',d)
|
||||
d = int(input(" Enter a value for d :"))
|
||||
except ValueError:
|
||||
print('That is not a valid entry')
|
||||
else:
|
||||
if mm != 'quit':
|
||||
ii= random.randint(0,6)
|
||||
statements = ["I sorry, Dave. I'm afraid i can't do that","I'm begging you....read the directions","Nah ahh ahh, didnt say the magic word","This input is....UNACCEPTABLE!!","Seriously....was that even a word???","Please follow the directions","Just type 'help' if you are really that lost"]
|
||||
print(statements[ii])
|
||||
18
Task/RSA-code/Python/rsa-code-3.py
Normal file
18
Task/RSA-code/Python/rsa-code-3.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
>>>
|
||||
To redefine n,e, or d, type 'n','e',... etc.
|
||||
To encrypt a message with the current key, type 'Encrypt'
|
||||
To decrypt a message with the current key, type 'Decrypt'
|
||||
Type quit to exit
|
||||
|
||||
|
||||
|
||||
|
||||
Enter Command...ENCRYPT
|
||||
Enter Plaintext :drink MORE Ovaltine
|
||||
Ciphertext: [140, 2222, 1864, 1616, 821, 384, 2038, 2116, 2222, 205, 384, 2116, 45, 1, 2497, 793, 1864, 1616, 205, 41]
|
||||
Number of Ciphertext blocks: 20
|
||||
Enter Command...decrypt
|
||||
Enter ciphertext blocks:[140, 2222, 1864, 1616, 821, 384, 2038, 2116, 2222, 205, 384, 2116, 45, 1, 2497, 793, 1864, 1616, 205, 41]
|
||||
Plaintext is: drink more ovaltineu
|
||||
Enter Command...quit
|
||||
>>>
|
||||
1
Task/RSA-code/README
Normal file
1
Task/RSA-code/README
Normal file
|
|
@ -0,0 +1 @@
|
|||
Data source: http://rosettacode.org/wiki/RSA_code
|
||||
172
Task/RSA-code/Racket/rsa-code.rkt
Normal file
172
Task/RSA-code/Racket/rsa-code.rkt
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
#lang racket
|
||||
(require math/number-theory)
|
||||
(define-logger rsa)
|
||||
(current-logger rsa-logger)
|
||||
|
||||
;; -| STRING TO NUMBER MAPPING |----------------------------------------------------------------------
|
||||
(define (bytes->number B) ; We'll need our data in numerical form ..
|
||||
(for/fold ((rv 0)) ((b B)) (+ b (* rv 256))))
|
||||
|
||||
(define (number->bytes N) ; .. and back again
|
||||
(define (inr n b) (if (zero? n) b (inr (quotient n 256) (bytes-append (bytes (modulo n 256)) b))))
|
||||
(inr N (bytes)))
|
||||
|
||||
;; -| RSA PUBLIC / PRIVATE FUNCTIONS |----------------------------------------------------------------
|
||||
;; The basic definitions... pretty well lifted from the text book!
|
||||
(define ((C e n) p)
|
||||
;; Just do the arithmetic to demonstrate RSA...
|
||||
;; breaking large messages into blocks is something for another day.
|
||||
(unless (< p n) (raise-argument-error 'C (format "(and/c integer? (</c ~a))" n) p))
|
||||
(modular-expt p e n))
|
||||
|
||||
(define ((P d n) c)
|
||||
(modular-expt c d n))
|
||||
|
||||
;; -| RSA KEY GENERATION |----------------------------------------------------------------------------
|
||||
;; Key generation
|
||||
;; Full description of the steps can be found on Wikipedia
|
||||
(define (RSA-keyset function-base-name)
|
||||
(log-info "RSA-keyset: ~s" function-base-name)
|
||||
(define max-k 4294967087)
|
||||
;; I'm guessing this RNG is about as cryptographically strong as replacing spaces with tabs.
|
||||
(define (big-random n-rolls)
|
||||
(for/fold ((rv 1)) ((roll (in-range n-rolls 0 -1))) (+ (* rv (add1 max-k)) 1 (random max-k))))
|
||||
(define (big-random-prime)
|
||||
(define start-number (big-random (/ 1024 32)))
|
||||
(log-debug "got large (possibly non-prime) number, finding next prime")
|
||||
(next-prime (match start-number ((? odd? o) o) ((app add1 e) e))))
|
||||
|
||||
;; [1] Choose two distinct prime numbers p and q.
|
||||
(log-debug "generating p")
|
||||
(define p (big-random-prime))
|
||||
(log-debug "p generated")
|
||||
(log-debug "generating q")
|
||||
(define q (big-random-prime))
|
||||
(log-debug "q generated")
|
||||
(log-info "primes generated")
|
||||
|
||||
;; [2] Compute n = pq.
|
||||
(define n (* p q))
|
||||
|
||||
;; [3] Compute φ(n) = φ(p)φ(q) = (p − 1)(q − 1) = n - (p + q -1),
|
||||
;; where φ is Euler's totient function.
|
||||
(define φ (- n (+ p q -1)))
|
||||
|
||||
;; [4] Choose an integer e such that 1 < e < φ(n) and gcd(e, φ(n)) = 1; i.e., e and φ(n) are
|
||||
;; coprime. ... most commonly 2^16 + 1 = 65,537 ...
|
||||
(define e (+ (expt 2 16) 1))
|
||||
|
||||
;; [5] Determine d as d ≡ e−1 (mod φ(n)); i.e., d is the multiplicative inverse of e (modulo φ(n)).
|
||||
(log-debug "generating d")
|
||||
(define d (modular-inverse e φ))
|
||||
(log-info "d generated")
|
||||
(values n e d))
|
||||
|
||||
;; -| GIVE A USABLE SET OF PRIVATE STUFF TO A USER |--------------------------------------------------
|
||||
;; six values: the public (encrypt) function (numeric)
|
||||
;; the private (decrypt) function (numeric)
|
||||
;; the public (encrypt) function (bytes)
|
||||
;; the private (decrypt) function (bytes)
|
||||
;; private (list n e d)
|
||||
;; public (list n e)
|
||||
(define (RSA-key-pack #:function-base-name function-base-name)
|
||||
(define (rnm-fn f s) (procedure-rename f (string->symbol (format "~a-~a" function-base-name s))))
|
||||
(define-values (n e d) (RSA-keyset function-base-name))
|
||||
(define my-C (rnm-fn (C e n) "C"))
|
||||
(define my-P (rnm-fn (P d n) "P"))
|
||||
(define my-encrypt (rnm-fn (compose number->bytes my-C bytes->number) "encrypt"))
|
||||
(define my-decrypt (rnm-fn (compose number->bytes my-P bytes->number) "decrypt"))
|
||||
(values my-C my-P my-encrypt my-decrypt (list n e d) (list n e)))
|
||||
|
||||
;; -| HEREON IS JUST A LOAD OF CHATTY DEMOS |---------------------------------------------------------
|
||||
(define (narrated-encrypt-bytes C who plain-text)
|
||||
(define plain-n (bytes->number plain-text))
|
||||
(define cypher-n (C plain-n))
|
||||
(define cypher-text (number->bytes cypher-n))
|
||||
(printf #<<EOS
|
||||
~a wants to send plain text: ~s
|
||||
as number: ~s
|
||||
cyphered number: ~s
|
||||
sent by ~a over the public interwebs:
|
||||
~s
|
||||
...
|
||||
|
||||
|
||||
EOS
|
||||
who plain-text plain-n cypher-n who cypher-text)
|
||||
cypher-text)
|
||||
|
||||
(define (narrated-decrypt-bytes P who cypher-text)
|
||||
(define cypher-n (bytes->number cypher-text))
|
||||
(define plain-n (P cypher-n))
|
||||
(define plain-text (number->bytes plain-n))
|
||||
(printf #<<EOS
|
||||
...
|
||||
~s
|
||||
received by ~a
|
||||
as number: ~s
|
||||
decyphered (with P) number: ~s
|
||||
decyphered text:
|
||||
~s
|
||||
|
||||
|
||||
EOS
|
||||
cypher-text who cypher-n plain-n plain-text)
|
||||
plain-text)
|
||||
|
||||
;; ENCRYPT AND DECRYPT A MESSAGE WITH THE e.g. KEYS
|
||||
(define-values (given-n given-e given-d)
|
||||
(values 9516311845790656153499716760847001433441357
|
||||
65537
|
||||
5617843187844953170308463622230283376298685))
|
||||
|
||||
;; Get the keys specific RSA functions
|
||||
(for ((message-text (list #"hello world" #"TOP SECRET!")))
|
||||
(define Bobs-public-function (C given-e given-n))
|
||||
(define Bobs-private-function (P given-d given-n))
|
||||
(define cypher-text (narrated-encrypt-bytes Bobs-public-function "Alice" message-text))
|
||||
(define plain-text (narrated-decrypt-bytes Bobs-private-function "Bob" cypher-text))
|
||||
plain-text)
|
||||
|
||||
;; Demonstrate with larger keys.
|
||||
;; (And include a free recap on digital signatures, too)
|
||||
(define-values (A-pub-C A-pvt-P A-pub-encrypt A-pvt-decrypt A-pvt-keys A-pub-keys)
|
||||
(RSA-key-pack #:function-base-name 'Alice))
|
||||
(define-values (B-pub-C B-pvt-P B-pub-encrypt B-pvt-decrypt B-pvt-keys B-pub-keys)
|
||||
(RSA-key-pack #:function-base-name 'Bob))
|
||||
|
||||
;; Since p and q are random, it is possible that message' = "message modulo {A,B}-key-n" will be too
|
||||
;; big for "message' modulo {B,A}-key-n", if that happens then I run the program again until it
|
||||
;; works. Strictly, we need blocking of the signed message -- which is not yet implemented.
|
||||
(let* ((plain-A-to-B #"Dear Bob, meet you in Lymm at 1200, Alice")
|
||||
(signed-A-to-B (A-pvt-decrypt plain-A-to-B))
|
||||
(unsigned-A-to-B (A-pub-encrypt signed-A-to-B))
|
||||
(crypt-signed-A-to-B (B-pub-encrypt signed-A-to-B))
|
||||
(decrypt-signed-A-to-B (B-pvt-decrypt crypt-signed-A-to-B))
|
||||
(decrypt-verified-B (A-pub-encrypt decrypt-signed-A-to-B)))
|
||||
(printf
|
||||
#<<EOS
|
||||
Alice wants to send ~s to Bob.
|
||||
She "encrypts" with her private "decryption" key.
|
||||
(A-prv msg) -> ~s
|
||||
Only she could have done this (only she has the her private key data) -- so this is a signature on the
|
||||
message. Anyone can verify the signature by "decrypting" the message with the public "encryption" key.
|
||||
(A-pub (A-prv msg)) -> ~s
|
||||
But anyone is able to do this, so there is no privacy here.
|
||||
Everyone knows that it can only be Alice at Lymm at noon, but this message is for Bob's eyes only.
|
||||
We need to encrypt this with his public key:
|
||||
(B-pub (A-prv msg)) -> ~s
|
||||
Which is what gets posted to alt.chat.secret-rendezvous
|
||||
Bob decrypts this to get the signed message from Alice:
|
||||
(B-prv (B-pub (A-prv msg))) -> ~s
|
||||
And verifies Alice's signature:
|
||||
(A-pub (B-prv (B-pub (A-prv msg)))) -> ~s
|
||||
Alice genuinely sent the message.
|
||||
And nobody else (on a.c.s-r, at least) has read it.
|
||||
|
||||
KEYS:
|
||||
Alice's full set: ~s
|
||||
Bob's full set: ~s
|
||||
EOS
|
||||
plain-A-to-B signed-A-to-B unsigned-A-to-B crypt-signed-A-to-B decrypt-signed-A-to-B
|
||||
decrypt-verified-B A-pvt-keys B-pvt-keys))
|
||||
30
Task/RSA-code/Seed7/rsa-code.seed7
Normal file
30
Task/RSA-code/Seed7/rsa-code.seed7
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
$ include "seed7_05.s7i";
|
||||
include "bigint.s7i";
|
||||
include "bytedata.s7i";
|
||||
|
||||
const proc: main is func
|
||||
local
|
||||
const string: plainText is "Rosetta Code";
|
||||
# Use a key big enough to hold 16 bytes of plain text in a single block.
|
||||
const bigInteger: modulus is 9516311845790656153499716760847001433441357_;
|
||||
const bigInteger: encode is 65537_;
|
||||
const bigInteger: decode is 5617843187844953170308463622230283376298685_;
|
||||
var bigInteger: plainTextNumber is 0_;
|
||||
var bigInteger: encodedNumber is 0_;
|
||||
var bigInteger: decodedNumber is 0_;
|
||||
var string: decodedText is "";
|
||||
begin
|
||||
writeln("Plain text: " <& plainText);
|
||||
plainTextNumber := bytes2BigInt(plainText, UNSIGNED, BE);
|
||||
if plainTextNumber >= modulus then
|
||||
writeln("Plain text message too long");
|
||||
else
|
||||
writeln("Plain text as a number: " <& plainTextNumber);
|
||||
encodedNumber := modPow(plainTextNumber, encode, modulus);
|
||||
writeln("Encoded: " <& encodedNumber);
|
||||
decodedNumber := modPow(encodedNumber, decode, modulus);
|
||||
writeln("Decoded: " <& decodedNumber);
|
||||
decodedText := bytes(decodedNumber, UNSIGNED, BE);
|
||||
writeln("Decoded number as text: " <& decodedText);
|
||||
end if;
|
||||
end func;
|
||||
48
Task/RSA-code/Tcl/rsa-code.tcl
Normal file
48
Task/RSA-code/Tcl/rsa-code.tcl
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package require Tcl 8.5
|
||||
|
||||
# This is a straight-forward square-and-multiply implementation that relies on
|
||||
# Tcl 8.5's bignum support (based on LibTomMath) for speed.
|
||||
proc modexp {b expAndMod} {
|
||||
lassign $expAndMod -> e n
|
||||
if {$b >= $n} {puts stderr "WARNING: modulus too small"}
|
||||
for {set r 1} {$e != 0} {set e [expr {$e >> 1}]} {
|
||||
if {$e & 1} {
|
||||
set r [expr {($r * $b) % $n}]
|
||||
}
|
||||
set b [expr {($b ** 2) % $n}]
|
||||
}
|
||||
return $r
|
||||
}
|
||||
|
||||
# Assumes that messages are shorter than the modulus
|
||||
proc rsa_encrypt {message publicKey} {
|
||||
if {[lindex $publicKey 0] ne "publicKey"} {error "key handling"}
|
||||
set toEnc 0
|
||||
foreach char [split [encoding convertto utf-8 $message] ""] {
|
||||
set toEnc [expr {$toEnc * 256 + [scan $char "%c"]}]
|
||||
}
|
||||
return [modexp $toEnc $publicKey]
|
||||
}
|
||||
|
||||
proc rsa_decrypt {encrypted privateKey} {
|
||||
if {[lindex $privateKey 0] ne "privateKey"} {error "key handling"}
|
||||
set toDec [modexp $encrypted $privateKey]
|
||||
for {set message ""} {$toDec > 0} {set toDec [expr {$toDec >> 8}]} {
|
||||
append message [format "%c" [expr {$toDec & 255}]]
|
||||
}
|
||||
return [encoding convertfrom utf-8 [string reverse $message]]
|
||||
}
|
||||
|
||||
# Assemble packaged public and private keys
|
||||
set e 65537
|
||||
set n 9516311845790656153499716760847001433441357
|
||||
set d 5617843187844953170308463622230283376298685
|
||||
set publicKey [list "publicKey" $e $n]
|
||||
set privateKey [list "privateKey" $d $n]
|
||||
|
||||
# Test on some input strings
|
||||
foreach input {"Rosetta Code" "UTF-8 \u263a test"} {
|
||||
set enc [rsa_encrypt $input $publicKey]
|
||||
set dec [rsa_decrypt $enc $privateKey]
|
||||
puts "$input -> $enc -> $dec"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue