mirror of
https://github.com/arnaucube/cryptofun.git
synced 2026-02-28 05:16:46 +01:00
paillier encrypt & decrypt, homomorphic addition
This commit is contained in:
@@ -14,5 +14,10 @@ Crypto algorithms from scratch. Academic purposes only.
|
|||||||
- [x] Homomorphic Multiplication
|
- [x] Homomorphic Multiplication
|
||||||
|
|
||||||
## Paillier
|
## Paillier
|
||||||
|
- [x] GenerateKeyPair
|
||||||
|
- [x] Encrypt
|
||||||
|
- [x] Decrypt
|
||||||
|
- [x] Homomorphic Addition
|
||||||
|
|
||||||
## ECC
|
## ECC
|
||||||
## Shamir Secret Sharing
|
## Shamir Secret Sharing
|
||||||
|
|||||||
111
paillier/paillier.go
Normal file
111
paillier/paillier.go
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
package paillier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
prime "../prime"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
bits = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
type PublicKey struct {
|
||||||
|
N *big.Int `json:"n"`
|
||||||
|
G *big.Int `json:"g"`
|
||||||
|
}
|
||||||
|
type PrivateKey struct {
|
||||||
|
Lambda *big.Int `json:"lambda"`
|
||||||
|
Mu *big.Int `json:"mu"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Key struct {
|
||||||
|
PubK PublicKey
|
||||||
|
PrivK PrivateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateKeyPair() (key Key, err error) {
|
||||||
|
p, err := rand.Prime(rand.Reader, bits/2)
|
||||||
|
if err != nil {
|
||||||
|
return key, err
|
||||||
|
}
|
||||||
|
q, err := rand.Prime(rand.Reader, bits/2)
|
||||||
|
if err != nil {
|
||||||
|
return key, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pq := new(big.Int).Mul(p, q)
|
||||||
|
p1q1 := big.NewInt((p.Int64() - 1) * (q.Int64() - 1))
|
||||||
|
gcd := new(big.Int).GCD(nil, nil, pq, p1q1)
|
||||||
|
if gcd.Int64() != int64(1) {
|
||||||
|
return key, errors.New("gcd comprovation failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
n := new(big.Int).Mul(p, q)
|
||||||
|
lambda := big.NewInt(int64(Lcm(float64(p.Int64())-1, float64(q.Int64())-1)))
|
||||||
|
|
||||||
|
//g generation
|
||||||
|
alpha := big.NewInt(int64(prime.RandInt(0, int(n.Int64()))))
|
||||||
|
beta := big.NewInt(int64(prime.RandInt(0, int(n.Int64()))))
|
||||||
|
alphan := new(big.Int).Mul(alpha, n)
|
||||||
|
alphan1 := new(big.Int).Add(alphan, big.NewInt(1))
|
||||||
|
betaN := new(big.Int).Exp(beta, n, nil)
|
||||||
|
ab := new(big.Int).Mul(alphan1, betaN)
|
||||||
|
n2 := new(big.Int).Mul(n, n)
|
||||||
|
g := new(big.Int).Mod(ab, n2)
|
||||||
|
//in some Paillier implementations use this:
|
||||||
|
// g = new(big.Int).Add(n, big.NewInt(1))
|
||||||
|
|
||||||
|
key.PubK.N = n
|
||||||
|
key.PubK.G = g
|
||||||
|
|
||||||
|
//mu generation
|
||||||
|
Glambda := new(big.Int).Exp(g, lambda, nil)
|
||||||
|
u := new(big.Int).Mod(Glambda, n2)
|
||||||
|
L := L(u, n)
|
||||||
|
mu := new(big.Int).ModInverse(L, n)
|
||||||
|
|
||||||
|
key.PrivK.Lambda = lambda
|
||||||
|
key.PrivK.Mu = mu
|
||||||
|
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Lcm(a, b float64) float64 {
|
||||||
|
r := (a * b) / float64(prime.Gcd(int(a), int(b)))
|
||||||
|
return r
|
||||||
|
|
||||||
|
}
|
||||||
|
func L(u *big.Int, n *big.Int) *big.Int {
|
||||||
|
u1 := new(big.Int).Sub(u, big.NewInt(1))
|
||||||
|
L := new(big.Int).Div(u1, n)
|
||||||
|
return L
|
||||||
|
}
|
||||||
|
|
||||||
|
func Encrypt(m *big.Int, pubK PublicKey) *big.Int {
|
||||||
|
gM := new(big.Int).Exp(pubK.G, m, nil)
|
||||||
|
r := big.NewInt(int64(prime.RandInt(0, int(pubK.N.Int64()))))
|
||||||
|
rN := new(big.Int).Exp(r, pubK.N, nil)
|
||||||
|
gMrN := new(big.Int).Mul(gM, rN)
|
||||||
|
n2 := new(big.Int).Mul(pubK.N, pubK.N)
|
||||||
|
c := new(big.Int).Mod(gMrN, n2)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
func Decrypt(c *big.Int, pubK PublicKey, privK PrivateKey) *big.Int {
|
||||||
|
cLambda := new(big.Int).Exp(c, privK.Lambda, nil)
|
||||||
|
n2 := new(big.Int).Mul(pubK.N, pubK.N)
|
||||||
|
u := new(big.Int).Mod(cLambda, n2)
|
||||||
|
L := L(u, pubK.N)
|
||||||
|
LMu := new(big.Int).Mul(L, privK.Mu)
|
||||||
|
m := new(big.Int).Mod(LMu, pubK.N)
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func HomomorphicAddition(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
|
||||||
|
}
|
||||||
41
paillier/paillier_test.go
Normal file
41
paillier/paillier_test.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package paillier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEncryptDecrypt(t *testing.T) {
|
||||||
|
key, err := GenerateKeyPair()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(err.Error())
|
||||||
|
}
|
||||||
|
fmt.Println(key)
|
||||||
|
mBytes := []byte("Hi")
|
||||||
|
m := new(big.Int).SetBytes(mBytes)
|
||||||
|
c := Encrypt(m, key.PubK)
|
||||||
|
d := Decrypt(c, key.PubK, key.PrivK)
|
||||||
|
if m == d {
|
||||||
|
fmt.Println(key)
|
||||||
|
t.Errorf("m not equal to decrypted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHomomorphicAddition(t *testing.T) {
|
||||||
|
key, err := GenerateKeyPair()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(err.Error())
|
||||||
|
}
|
||||||
|
n1 := big.NewInt(int64(110))
|
||||||
|
n2 := big.NewInt(int64(150))
|
||||||
|
c1 := Encrypt(n1, key.PubK)
|
||||||
|
c2 := Encrypt(n2, key.PubK)
|
||||||
|
c3c4 := HomomorphicAddition(c1, c2, key.PubK)
|
||||||
|
d := Decrypt(c3c4, key.PubK, key.PrivK)
|
||||||
|
if !bytes.Equal(new(big.Int).Add(n1, n2).Bytes(), d.Bytes()) {
|
||||||
|
fmt.Println(key)
|
||||||
|
t.Errorf("decrypted result not equal to original result")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,11 @@ package prime
|
|||||||
|
|
||||||
import "math/rand"
|
import "math/rand"
|
||||||
|
|
||||||
|
const (
|
||||||
|
MaxPrime = 2000
|
||||||
|
MinPrime = 500
|
||||||
|
)
|
||||||
|
|
||||||
func RandInt(min int, max int) int {
|
func RandInt(min int, max int) int {
|
||||||
r := rand.Intn(max-min) + min
|
r := rand.Intn(max-min) + min
|
||||||
return r
|
return r
|
||||||
|
|||||||
43
rsa/rsa.go
43
rsa/rsa.go
@@ -2,18 +2,16 @@ package rsa
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
prime "../prime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MaxPrime = 2000
|
bits = 512 // 2048
|
||||||
MinPrime = 500
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var bigOne = big.NewInt(int64(1))
|
||||||
|
|
||||||
type PublicKey struct {
|
type PublicKey struct {
|
||||||
E *big.Int `json:"e"`
|
E *big.Int `json:"e"`
|
||||||
N *big.Int `json:"n"`
|
N *big.Int `json:"n"`
|
||||||
@@ -32,37 +30,42 @@ type Key struct {
|
|||||||
PrivK PrivateKey
|
PrivK PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateKeyPair() (key Key) {
|
func GenerateKeyPair() (key Key, err error) {
|
||||||
rand.Seed(time.Now().Unix())
|
p, err := rand.Prime(rand.Reader, bits/2)
|
||||||
p := prime.RandPrime(MinPrime, MaxPrime)
|
if err != nil {
|
||||||
q := prime.RandPrime(MinPrime, MaxPrime)
|
return key, err
|
||||||
|
}
|
||||||
|
q, err := rand.Prime(rand.Reader, bits/2)
|
||||||
|
if err != nil {
|
||||||
|
return key, err
|
||||||
|
}
|
||||||
|
|
||||||
n := p * q
|
n := new(big.Int).Mul(p, q)
|
||||||
phi := (p - 1) * (q - 1)
|
p_1 := new(big.Int).Sub(p, bigOne)
|
||||||
|
q_1 := new(big.Int).Sub(q, bigOne)
|
||||||
|
phi := new(big.Int).Mul(p_1, q_1)
|
||||||
e := 65537
|
e := 65537
|
||||||
var pubK PublicKey
|
var pubK PublicKey
|
||||||
pubK.E = big.NewInt(int64(e))
|
pubK.E = big.NewInt(int64(e))
|
||||||
pubK.N = big.NewInt(int64(n))
|
pubK.N = n
|
||||||
|
|
||||||
d := new(big.Int).ModInverse(big.NewInt(int64(e)), big.NewInt(int64(phi)))
|
d := new(big.Int).ModInverse(big.NewInt(int64(e)), phi)
|
||||||
|
|
||||||
var privK PrivateKey
|
var privK PrivateKey
|
||||||
privK.D = d
|
privK.D = d
|
||||||
privK.N = big.NewInt(int64(n))
|
privK.N = n
|
||||||
|
|
||||||
key.PubK = pubK
|
key.PubK = pubK
|
||||||
key.PrivK = privK
|
key.PrivK = privK
|
||||||
return key
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Encrypt(m *big.Int, pubK PublicKey) *big.Int {
|
func Encrypt(m *big.Int, pubK PublicKey) *big.Int {
|
||||||
Me := new(big.Int).Exp(m, pubK.E, nil)
|
c := new(big.Int).Exp(m, pubK.E, pubK.N)
|
||||||
c := new(big.Int).Mod(Me, pubK.N)
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
func Decrypt(c *big.Int, privK PrivateKey) *big.Int {
|
func Decrypt(c *big.Int, privK PrivateKey) *big.Int {
|
||||||
Cd := new(big.Int).Exp(c, privK.D, nil)
|
m := new(big.Int).Exp(c, privK.D, privK.N)
|
||||||
m := new(big.Int).Mod(Cd, privK.N)
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,17 @@ package rsa
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEncryptDecrypt(t *testing.T) {
|
func TestEncryptDecrypt(t *testing.T) {
|
||||||
key := GenerateKeyPair()
|
key, err := GenerateKeyPair()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(err.Error())
|
||||||
|
}
|
||||||
|
fmt.Println(key)
|
||||||
mBytes := []byte("Hi")
|
mBytes := []byte("Hi")
|
||||||
m := new(big.Int).SetBytes(mBytes)
|
m := new(big.Int).SetBytes(mBytes)
|
||||||
c := Encrypt(m, key.PubK)
|
c := Encrypt(m, key.PubK)
|
||||||
@@ -19,7 +23,10 @@ func TestEncryptDecrypt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestBlindSignature(t *testing.T) {
|
func TestBlindSignature(t *testing.T) {
|
||||||
key := GenerateKeyPair()
|
key, err := GenerateKeyPair()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
mBytes := []byte("Hi")
|
mBytes := []byte("Hi")
|
||||||
m := new(big.Int).SetBytes(mBytes)
|
m := new(big.Int).SetBytes(mBytes)
|
||||||
@@ -39,8 +46,11 @@ func TestBlindSignature(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHomomorphiMultiplication(t *testing.T) {
|
func TestHomomorphicMultiplication(t *testing.T) {
|
||||||
key := GenerateKeyPair()
|
key, err := GenerateKeyPair()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
n1 := big.NewInt(int64(11))
|
n1 := big.NewInt(int64(11))
|
||||||
n2 := big.NewInt(int64(15))
|
n2 := big.NewInt(int64(15))
|
||||||
|
|||||||
Reference in New Issue
Block a user