1
+ package main
2
+
3
+ import (
4
+ "math/big"
5
+ crypto"crypto/rand"
6
+ "strconv"
7
+ "fmt"
8
+ )
9
+ /*
10
+ Care has been taken to uses cryptographic secure functions
11
+ The primes numbers are 1024 bits which is as secure as u can get really
12
+ crypto/rand library has been imported as crypto and not rand
13
+ This import style will make it easier to spot all the cryptographic secure functions
14
+ */
15
+ func main (){
16
+ p ,_ := crypto .Prime (crypto .Reader ,1024 )
17
+ q ,_ := crypto .Prime (crypto .Reader ,1024 )
18
+ if ! (primeCheck (p )|| primeCheck (q )){
19
+ //they are always prime, no worries
20
+ fmt .Println ("These numbers ain't prime" )
21
+ }
22
+ n := new (big.Int ).Mul (p ,q )
23
+
24
+ one := big .NewInt (1 )
25
+
26
+ delta := lcmBig (p .Sub (p ,one ),q .Sub (q ,one ))
27
+
28
+ e ,_ := crypto .Prime (crypto .Reader ,delta .BitLen ())
29
+ d := big .NewInt (0 )
30
+ d .ModInverse (e ,delta )
31
+
32
+ cleartext := "Black Lives Matter, all lives can't matter until Black lives matter"
33
+ runes := []rune (cleartext )
34
+ ASCIIs := toASCII (runes )
35
+ stringEncoded := stringEncode (ASCIIs )
36
+ bigNum , _ := new (big.Int ).SetString (stringEncoded ,0 )
37
+ /*
38
+ TODO: check that bigNum is not larger than N if larger break
39
+ into two or more strings and encrypt separately
40
+ */
41
+ fmt .Printf ("Message to be encrypted: %v \n " ,cleartext )
42
+ fmt .Printf ("ASCII encoded: %v\n " ,bigNum )
43
+ encrypted := encryptBig (bigNum ,e ,n )
44
+ fmt .Printf ("ciphertext: %v \n " ,encrypted )
45
+ decrypted := decryptBig (encrypted ,d ,n )
46
+ fmt .Printf ("Decrypted but still ASCII encoded: %v \n " ,decrypted )
47
+ decryptASCIIs := stringDecode (decrypted )
48
+ fmt .Printf ("Plaintext (original message) :%v" ,toRune (decryptASCIIs ))
49
+ }
50
+
51
+ func encryptBig (num * big.Int , privateExponent * big.Int , modulus * big.Int )* big.Int {
52
+ //encrypts by modular exponentiation
53
+ encrypted := new (big.Int ).Exp (num ,privateExponent ,modulus )
54
+ return encrypted
55
+ }
56
+
57
+ func decryptBig (num * big.Int , publicExponent * big.Int , modulus * big.Int )* big.Int {
58
+ //decrypts by modular exponentiation
59
+ decrypted := new (big.Int ).Exp (num ,publicExponent ,modulus )
60
+ return decrypted
61
+ }
62
+
63
+ func lcmBig (x * big.Int , y * big.Int )* big.Int {
64
+ //an lcm implementation for big.Int numbers
65
+ gcd := new (big.Int ).GCD (nil ,nil ,x ,y )
66
+ temp := new (big.Int ).Mul (x ,y )
67
+ lcm := new (big.Int ).Div (temp ,gcd )
68
+ return lcm
69
+ }
70
+
71
+ func primeCheck (prime * big.Int )bool {
72
+ //primality test
73
+ return prime .ProbablyPrime (256 )
74
+ }
75
+
76
+ func toASCII (slice []rune )[]int {
77
+ //runs in O(n) where n = len(slice)
78
+ var converted []int
79
+ for _ ,v := range slice {
80
+ converted = append (converted , int (v ))
81
+ }
82
+ return converted
83
+ }
84
+
85
+ func toRune (slice []int )string {
86
+ //runs in O(n) where n = len(slice)
87
+ var str string
88
+ for _ ,v := range slice {
89
+ str += string (v )
90
+ }
91
+ return str
92
+ }
93
+
94
+ func stringEncode (slice []int )string {
95
+ //encodes the ASCII to a string
96
+ var out []string
97
+ for _ ,v := range slice {
98
+ if v < 100 {
99
+ out = append (out ,"0" + strconv .Itoa (v ))
100
+ continue
101
+ }
102
+ out = append (out , strconv .Itoa (v ))
103
+ }
104
+ var str string
105
+ for _ ,v := range out {
106
+ str += v
107
+ }
108
+ /*strips leading 0 if present to avoid conversion errors
109
+ */
110
+ if str [0 ]== '0' {
111
+ str = str [1 :]
112
+ }
113
+ return str
114
+ }
115
+
116
+ func stringDecode (decryptedBig * big.Int )[]int {
117
+ //decodes the number to string then ASCII values
118
+ str := decryptedBig .String ()
119
+ if len (str )% 3 != 0 {
120
+ str = "0" + str
121
+ }
122
+ var ASCII []int
123
+ for i := 0 ; i < len (str ); i += 3 {
124
+ temp ,_ := strconv .Atoi (str [i :i + 3 ])
125
+ ASCII = append (ASCII ,temp )
126
+ }
127
+ return ASCII
128
+ }
0 commit comments