mirror of
https://github.com/arnaucube/cryptofun.git
synced 2026-02-28 05:16:46 +01:00
rsa encrypt & decrypt, blind signatures, homomorphic multiplication
This commit is contained in:
18
README.md
Normal file
18
README.md
Normal file
@@ -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
|
||||
49
prime/prime.go
Normal file
49
prime/prime.go
Normal file
@@ -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)
|
||||
}
|
||||
98
rsa/rsa.go
Normal file
98
rsa/rsa.go
Normal file
@@ -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
|
||||
}
|
||||
54
rsa/rsa_test.go
Normal file
54
rsa/rsa_test.go
Normal file
@@ -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")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user