@ -0,0 +1,18 @@ |
|||
# cryptofun |
|||
|
|||
Crypto algorithms from scratch. Academic purposes only. |
|||
|
|||
|
|||
## RSA |
|||
- [x] GenerateKeyPair |
|||
- [x] Encrypt |
|||
- [x] Decrypt |
|||
- [x] Blind |
|||
- [x] Blind Signature |
|||
- [x] Unblind Signature |
|||
- [x] Verify Signature |
|||
- [x] Homomorphic Multiplication |
|||
|
|||
## Paillier |
|||
## ECC |
|||
## Shamir Secret Sharing |
@ -0,0 +1,49 @@ |
|||
package prime |
|||
|
|||
import "math/rand" |
|||
|
|||
func RandInt(min int, max int) int { |
|||
r := rand.Intn(max-min) + min |
|||
return r |
|||
} |
|||
func RandPrime(min int, max int) int { |
|||
primes := SieveOfEratosthenes(max) |
|||
randN := rand.Intn(len(primes)-0) + 0 |
|||
return primes[randN] |
|||
} |
|||
|
|||
// return list of primes less than N
|
|||
func SieveOfEratosthenes(N int) (primes []int) { |
|||
b := make([]bool, N) |
|||
for i := 2; i < N; i++ { |
|||
if b[i] == true { |
|||
continue |
|||
} |
|||
primes = append(primes, i) |
|||
for k := i * i; k < N; k += i { |
|||
b[k] = true |
|||
} |
|||
} |
|||
return |
|||
} |
|||
|
|||
func Gcd(a, b int) int { |
|||
var bgcd func(a, b, res int) int |
|||
bgcd = func(a, b, res int) int { |
|||
switch { |
|||
case a == b: |
|||
return res * a |
|||
case a%2 == 0 && b%2 == 0: |
|||
return bgcd(a/2, b/2, 2*res) |
|||
case a%2 == 0: |
|||
return bgcd(a/2, b, res) |
|||
case b%2 == 0: |
|||
return bgcd(a, b/2, res) |
|||
case a > b: |
|||
return bgcd(a-b, b, res) |
|||
default: |
|||
return bgcd(a, b-a, res) |
|||
} |
|||
} |
|||
return bgcd(a, b, 1) |
|||
} |
@ -0,0 +1,98 @@ |
|||
package rsa |
|||
|
|||
import ( |
|||
"bytes" |
|||
"math/big" |
|||
"math/rand" |
|||
"time" |
|||
|
|||
prime "../prime" |
|||
) |
|||
|
|||
const ( |
|||
MaxPrime = 2000 |
|||
MinPrime = 500 |
|||
) |
|||
|
|||
type PublicKey struct { |
|||
E *big.Int `json:"e"` |
|||
N *big.Int `json:"n"` |
|||
} |
|||
type PublicKeyString struct { |
|||
E string `json:"e"` |
|||
N string `json:"n"` |
|||
} |
|||
type PrivateKey struct { |
|||
D *big.Int `json:"d"` |
|||
N *big.Int `json:"n"` |
|||
} |
|||
|
|||
type Key struct { |
|||
PubK PublicKey |
|||
PrivK PrivateKey |
|||
} |
|||
|
|||
func GenerateKeyPair() (key Key) { |
|||
rand.Seed(time.Now().Unix()) |
|||
p := prime.RandPrime(MinPrime, MaxPrime) |
|||
q := prime.RandPrime(MinPrime, MaxPrime) |
|||
|
|||
n := p * q |
|||
phi := (p - 1) * (q - 1) |
|||
e := 65537 |
|||
var pubK PublicKey |
|||
pubK.E = big.NewInt(int64(e)) |
|||
pubK.N = big.NewInt(int64(n)) |
|||
|
|||
d := new(big.Int).ModInverse(big.NewInt(int64(e)), big.NewInt(int64(phi))) |
|||
|
|||
var privK PrivateKey |
|||
privK.D = d |
|||
privK.N = big.NewInt(int64(n)) |
|||
|
|||
key.PubK = pubK |
|||
key.PrivK = privK |
|||
return key |
|||
} |
|||
|
|||
func Encrypt(m *big.Int, pubK PublicKey) *big.Int { |
|||
Me := new(big.Int).Exp(m, pubK.E, nil) |
|||
c := new(big.Int).Mod(Me, pubK.N) |
|||
return c |
|||
} |
|||
func Decrypt(c *big.Int, privK PrivateKey) *big.Int { |
|||
Cd := new(big.Int).Exp(c, privK.D, nil) |
|||
m := new(big.Int).Mod(Cd, privK.N) |
|||
return m |
|||
} |
|||
|
|||
func Blind(m *big.Int, r *big.Int, pubK PublicKey) *big.Int { |
|||
rE := new(big.Int).Exp(r, pubK.E, nil) |
|||
mrE := new(big.Int).Mul(m, rE) |
|||
mBlinded := new(big.Int).Mod(mrE, pubK.N) |
|||
return mBlinded |
|||
} |
|||
|
|||
func BlindSign(m *big.Int, privK PrivateKey) *big.Int { |
|||
sigma := new(big.Int).Exp(m, privK.D, privK.N) |
|||
return sigma |
|||
} |
|||
func Unblind(sigma *big.Int, r *big.Int, pubK PublicKey) *big.Int { |
|||
r1 := new(big.Int).ModInverse(r, pubK.N) |
|||
bsr := new(big.Int).Mul(sigma, r1) |
|||
sig := new(big.Int).Mod(bsr, pubK.N) |
|||
return sig |
|||
} |
|||
func Verify(msg *big.Int, mSigned *big.Int, pubK PublicKey) bool { |
|||
//decrypt the mSigned with pubK
|
|||
Cd := new(big.Int).Exp(mSigned, pubK.E, nil) |
|||
m := new(big.Int).Mod(Cd, pubK.N) |
|||
return bytes.Equal(msg.Bytes(), m.Bytes()) |
|||
} |
|||
|
|||
func HomomorphicMul(c1 *big.Int, c2 *big.Int, pubK PublicKey) *big.Int { |
|||
c1c2 := new(big.Int).Mul(c1, c2) |
|||
n2 := new(big.Int).Mul(pubK.N, pubK.N) |
|||
d := new(big.Int).Mod(c1c2, n2) |
|||
return d |
|||
} |
@ -0,0 +1,54 @@ |
|||
package rsa |
|||
|
|||
import ( |
|||
"bytes" |
|||
"math/big" |
|||
"testing" |
|||
) |
|||
|
|||
func TestEncryptDecrypt(t *testing.T) { |
|||
key := GenerateKeyPair() |
|||
|
|||
mBytes := []byte("Hi") |
|||
m := new(big.Int).SetBytes(mBytes) |
|||
c := Encrypt(m, key.PubK) |
|||
|
|||
d := Decrypt(c, key.PrivK) |
|||
if m == d { |
|||
t.Errorf("m not equal to decrypted") |
|||
} |
|||
} |
|||
func TestBlindSignature(t *testing.T) { |
|||
key := GenerateKeyPair() |
|||
|
|||
mBytes := []byte("Hi") |
|||
m := new(big.Int).SetBytes(mBytes) |
|||
c := Encrypt(m, key.PubK) |
|||
|
|||
d := Decrypt(c, key.PrivK) |
|||
if m == d { |
|||
t.Errorf("decrypted d not equal to original m") |
|||
} |
|||
rVal := big.NewInt(int64(101)) |
|||
mBlinded := Blind(m, rVal, key.PubK) |
|||
sigma := BlindSign(mBlinded, key.PrivK) |
|||
mSigned := Unblind(sigma, rVal, key.PubK) |
|||
verified := Verify(m, mSigned, key.PubK) |
|||
if !verified { |
|||
t.Errorf("false, signature not verified") |
|||
} |
|||
} |
|||
|
|||
func TestHomomorphiMultiplication(t *testing.T) { |
|||
key := GenerateKeyPair() |
|||
|
|||
n1 := big.NewInt(int64(11)) |
|||
n2 := big.NewInt(int64(15)) |
|||
c1 := Encrypt(n1, key.PubK) |
|||
c2 := Encrypt(n2, key.PubK) |
|||
c3c4 := HomomorphicMul(c1, c2, key.PubK) |
|||
d := Decrypt(c3c4, key.PrivK) |
|||
if !bytes.Equal(new(big.Int).Mul(n1, n2).Bytes(), d.Bytes()) { |
|||
t.Errorf("decrypted result not equal to original result") |
|||
} |
|||
} |