diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..34c385a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +fmt diff --git a/README.md b/README.md index 35a4fd5..cba0cf2 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ Crypto algorithms from scratch. Academic purposes only. ## RSA +https://en.wikipedia.org/wiki/RSA_(cryptosystem)# - [x] GenerateKeyPair - [x] Encrypt - [x] Decrypt @@ -14,10 +15,15 @@ Crypto algorithms from scratch. Academic purposes only. - [x] Homomorphic Multiplication ## Paillier +https://en.wikipedia.org/wiki/Paillier_cryptosystem - [x] GenerateKeyPair - [x] Encrypt - [x] Decrypt - [x] Homomorphic Addition -## ECC ## Shamir Secret Sharing +https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing +- [x] create secret sharing from NumOfSecretsNeed, NumOfShares, RandPointP, SecretToShare +- [x] Lagrange Interpolation to restore the secret from the shares + +## ECC diff --git a/paillier/paillier.go b/paillier/paillier.go index cbbb78e..bee66ae 100644 --- a/paillier/paillier.go +++ b/paillier/paillier.go @@ -12,20 +12,25 @@ const ( bits = 16 ) +// PublicKey stores the public key data type PublicKey struct { N *big.Int `json:"n"` G *big.Int `json:"g"` } + +// PrivateKey stores the private key data type PrivateKey struct { Lambda *big.Int `json:"lambda"` Mu *big.Int `json:"mu"` } +// Key stores the public and private key data type Key struct { PubK PublicKey PrivK PrivateKey } +// GenerateKeyPair generates a random private and public key func GenerateKeyPair() (key Key, err error) { p, err := rand.Prime(rand.Reader, bits/2) if err != nil { @@ -44,7 +49,7 @@ func GenerateKeyPair() (key Key, err error) { } n := new(big.Int).Mul(p, q) - lambda := big.NewInt(int64(Lcm(float64(p.Int64())-1, float64(q.Int64())-1))) + 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())))) @@ -64,7 +69,7 @@ func GenerateKeyPair() (key Key, err error) { //mu generation Glambda := new(big.Int).Exp(g, lambda, nil) u := new(big.Int).Mod(Glambda, n2) - L := L(u, n) + L := l(u, n) mu := new(big.Int).ModInverse(L, n) key.PrivK.Lambda = lambda @@ -73,17 +78,18 @@ func GenerateKeyPair() (key Key, err error) { return key, nil } -func Lcm(a, b float64) float64 { +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 { +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 } +// Encrypt encrypts a message m with given PublicKey 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())))) @@ -93,16 +99,19 @@ func Encrypt(m *big.Int, pubK PublicKey) *big.Int { c := new(big.Int).Mod(gMrN, n2) return c } + +// Decrypt deencrypts a ciphertext c with given PublicKey and PrivateKey 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) + L := l(u, pubK.N) LMu := new(big.Int).Mul(L, privK.Mu) m := new(big.Int).Mod(LMu, pubK.N) return m } +// HomomorphicAddition calculates the addition of tow encrypted values given a PublicKey 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) diff --git a/paillier/paillier_test.go b/paillier/paillier_test.go index e5a7959..817e834 100644 --- a/paillier/paillier_test.go +++ b/paillier/paillier_test.go @@ -12,7 +12,6 @@ func TestEncryptDecrypt(t *testing.T) { if err != nil { t.Errorf(err.Error()) } - fmt.Println(key) mBytes := []byte("Hi") m := new(big.Int).SetBytes(mBytes) c := Encrypt(m, key.PubK) diff --git a/prime/prime.go b/prime/prime.go index ebd0e3f..de02445 100644 --- a/prime/prime.go +++ b/prime/prime.go @@ -3,21 +3,26 @@ package prime import "math/rand" const ( + // MaxPrime is to get a prime value below this number MaxPrime = 2000 + // MinPrime is to get a prime value above this number MinPrime = 500 ) +// RandInt returns a random integer between two values func RandInt(min int, max int) int { r := rand.Intn(max-min) + min return r } + +// RandPrime returns a random prime number between two values 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 +// SieveOfEratosthenes returns a list of primes less than N func SieveOfEratosthenes(N int) (primes []int) { b := make([]bool, N) for i := 2; i < N; i++ { @@ -32,6 +37,7 @@ func SieveOfEratosthenes(N int) (primes []int) { return } +// Gcd returns the greatest common divisor func Gcd(a, b int) int { var bgcd func(a, b, res int) int bgcd = func(a, b, res int) int { diff --git a/rsa/rsa.go b/rsa/rsa.go index 3ed54e5..e262a06 100644 --- a/rsa/rsa.go +++ b/rsa/rsa.go @@ -12,24 +12,25 @@ const ( var bigOne = big.NewInt(int64(1)) +// PublicKey stores the public key data type PublicKey struct { E *big.Int `json:"e"` N *big.Int `json:"n"` } -type PublicKeyString struct { - E string `json:"e"` - N string `json:"n"` -} + +// PrivateKey stores the private key data type PrivateKey struct { D *big.Int `json:"d"` N *big.Int `json:"n"` } +// Key stores the public and private key data type Key struct { PubK PublicKey PrivK PrivateKey } +// GenerateKeyPair generates a random private and public key func GenerateKeyPair() (key Key, err error) { p, err := rand.Prime(rand.Reader, bits/2) if err != nil { @@ -41,9 +42,9 @@ func GenerateKeyPair() (key Key, err error) { } n := new(big.Int).Mul(p, q) - 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) + p1 := new(big.Int).Sub(p, bigOne) + q1 := new(big.Int).Sub(q, bigOne) + phi := new(big.Int).Mul(p1, q1) e := 65537 var pubK PublicKey pubK.E = big.NewInt(int64(e)) @@ -60,15 +61,19 @@ func GenerateKeyPair() (key Key, err error) { return key, nil } +// Encrypt encrypts a message m with given PublicKey func Encrypt(m *big.Int, pubK PublicKey) *big.Int { c := new(big.Int).Exp(m, pubK.E, pubK.N) return c } + +// Decrypt deencrypts a ciphertext c with given PrivateKey func Decrypt(c *big.Int, privK PrivateKey) *big.Int { m := new(big.Int).Exp(c, privK.D, privK.N) return m } +// Blind blinds a message 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) @@ -76,16 +81,21 @@ func Blind(m *big.Int, r *big.Int, pubK PublicKey) *big.Int { return mBlinded } +// BlindSign blind signs a message without knowing the content func BlindSign(m *big.Int, privK PrivateKey) *big.Int { sigma := new(big.Int).Exp(m, privK.D, privK.N) return sigma } + +// Unblind unblinds the Blinded Signature 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 } + +// Verify verifies the signature of a message given the PublicKey of the signer 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) @@ -93,6 +103,7 @@ func Verify(msg *big.Int, mSigned *big.Int, pubK PublicKey) bool { return bytes.Equal(msg.Bytes(), m.Bytes()) } +// HomomorphicMul calculates the multiplication of tow encrypted values given a PublicKey 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) diff --git a/rsa/rsa_test.go b/rsa/rsa_test.go index d2ebfc1..2443aa9 100644 --- a/rsa/rsa_test.go +++ b/rsa/rsa_test.go @@ -2,7 +2,6 @@ package rsa import ( "bytes" - "fmt" "math/big" "testing" ) @@ -12,7 +11,6 @@ func TestEncryptDecrypt(t *testing.T) { if err != nil { t.Errorf(err.Error()) } - fmt.Println(key) mBytes := []byte("Hi") m := new(big.Int).SetBytes(mBytes) c := Encrypt(m, key.PubK) diff --git a/secrets/secrets_test.go b/secrets/secrets_test.go new file mode 100644 index 0000000..b8a1439 --- /dev/null +++ b/secrets/secrets_test.go @@ -0,0 +1,45 @@ +package secrets + +import ( + "crypto/rand" + "math/big" + "testing" +) + +func TestCreate(t *testing.T) { + k := 123456789 + p, err := rand.Prime(rand.Reader, bits/2) + if err != nil { + t.Errorf(err.Error()) + } + + nNeededSecrets := big.NewInt(int64(3)) + nShares := big.NewInt(int64(6)) + shares, err := Create( + nNeededSecrets, + nShares, + p, + big.NewInt(int64(k))) + if err != nil { + t.Errorf(err.Error()) + } + + //generate sharesToUse + var sharesToUse [][]*big.Int + sharesToUse = append(sharesToUse, shares[2]) + sharesToUse = append(sharesToUse, shares[1]) + sharesToUse = append(sharesToUse, shares[0]) + secr := LagrangeInterpolation(sharesToUse, p) + + // fmt.Print("original secret: ") + // fmt.Println(k) + // fmt.Print("p: ") + // fmt.Println(p) + // fmt.Print("shares: ") + // fmt.Println(shares) + // fmt.Print("secret result: ") + // fmt.Println(secr) + if int64(k) != secr.Int64() { + t.Errorf("reconstructed secret not correspond to original secret") + } +} diff --git a/secrets/sercrets.go b/secrets/sercrets.go new file mode 100644 index 0000000..57a405c --- /dev/null +++ b/secrets/sercrets.go @@ -0,0 +1,114 @@ +package secrets + +import ( + "crypto/rand" + "errors" + "math/big" +) + +const ( + bits = 1024 +) + +// t: number of secrets needed +// n: number of shares +// p: random point +// k: secret to share +// Create calculates the secrets to share from given parameters +func Create(t, n, p, k *big.Int) (result [][]*big.Int, err error) { + if k.Cmp(p) > 0 { + return nil, errors.New("Error: need k