mirror of
https://github.com/arnaucube/cryptofun.git
synced 2026-02-28 05:16:46 +01:00
shamir secret sharing: create secret sharing, and reconstruct secret from shares with Langrange Interpolation
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
fmt
|
||||||
@@ -4,6 +4,7 @@ Crypto algorithms from scratch. Academic purposes only.
|
|||||||
|
|
||||||
|
|
||||||
## RSA
|
## RSA
|
||||||
|
https://en.wikipedia.org/wiki/RSA_(cryptosystem)#
|
||||||
- [x] GenerateKeyPair
|
- [x] GenerateKeyPair
|
||||||
- [x] Encrypt
|
- [x] Encrypt
|
||||||
- [x] Decrypt
|
- [x] Decrypt
|
||||||
@@ -14,10 +15,15 @@ Crypto algorithms from scratch. Academic purposes only.
|
|||||||
- [x] Homomorphic Multiplication
|
- [x] Homomorphic Multiplication
|
||||||
|
|
||||||
## Paillier
|
## Paillier
|
||||||
|
https://en.wikipedia.org/wiki/Paillier_cryptosystem
|
||||||
- [x] GenerateKeyPair
|
- [x] GenerateKeyPair
|
||||||
- [x] Encrypt
|
- [x] Encrypt
|
||||||
- [x] Decrypt
|
- [x] Decrypt
|
||||||
- [x] Homomorphic Addition
|
- [x] Homomorphic Addition
|
||||||
|
|
||||||
## ECC
|
|
||||||
## Shamir Secret Sharing
|
## 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
|
||||||
|
|||||||
@@ -12,20 +12,25 @@ const (
|
|||||||
bits = 16
|
bits = 16
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PublicKey stores the public key data
|
||||||
type PublicKey struct {
|
type PublicKey struct {
|
||||||
N *big.Int `json:"n"`
|
N *big.Int `json:"n"`
|
||||||
G *big.Int `json:"g"`
|
G *big.Int `json:"g"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrivateKey stores the private key data
|
||||||
type PrivateKey struct {
|
type PrivateKey struct {
|
||||||
Lambda *big.Int `json:"lambda"`
|
Lambda *big.Int `json:"lambda"`
|
||||||
Mu *big.Int `json:"mu"`
|
Mu *big.Int `json:"mu"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Key stores the public and private key data
|
||||||
type Key struct {
|
type Key struct {
|
||||||
PubK PublicKey
|
PubK PublicKey
|
||||||
PrivK PrivateKey
|
PrivK PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateKeyPair generates a random private and public key
|
||||||
func GenerateKeyPair() (key Key, err error) {
|
func GenerateKeyPair() (key Key, err error) {
|
||||||
p, err := rand.Prime(rand.Reader, bits/2)
|
p, err := rand.Prime(rand.Reader, bits/2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -44,7 +49,7 @@ func GenerateKeyPair() (key Key, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
n := new(big.Int).Mul(p, q)
|
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
|
//g generation
|
||||||
alpha := big.NewInt(int64(prime.RandInt(0, int(n.Int64()))))
|
alpha := big.NewInt(int64(prime.RandInt(0, int(n.Int64()))))
|
||||||
@@ -64,7 +69,7 @@ func GenerateKeyPair() (key Key, err error) {
|
|||||||
//mu generation
|
//mu generation
|
||||||
Glambda := new(big.Int).Exp(g, lambda, nil)
|
Glambda := new(big.Int).Exp(g, lambda, nil)
|
||||||
u := new(big.Int).Mod(Glambda, n2)
|
u := new(big.Int).Mod(Glambda, n2)
|
||||||
L := L(u, n)
|
L := l(u, n)
|
||||||
mu := new(big.Int).ModInverse(L, n)
|
mu := new(big.Int).ModInverse(L, n)
|
||||||
|
|
||||||
key.PrivK.Lambda = lambda
|
key.PrivK.Lambda = lambda
|
||||||
@@ -73,17 +78,18 @@ func GenerateKeyPair() (key Key, err error) {
|
|||||||
return key, nil
|
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)))
|
r := (a * b) / float64(prime.Gcd(int(a), int(b)))
|
||||||
return r
|
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))
|
u1 := new(big.Int).Sub(u, big.NewInt(1))
|
||||||
L := new(big.Int).Div(u1, n)
|
L := new(big.Int).Div(u1, n)
|
||||||
return L
|
return L
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encrypt encrypts a message m with given PublicKey
|
||||||
func Encrypt(m *big.Int, pubK PublicKey) *big.Int {
|
func Encrypt(m *big.Int, pubK PublicKey) *big.Int {
|
||||||
gM := new(big.Int).Exp(pubK.G, m, nil)
|
gM := new(big.Int).Exp(pubK.G, m, nil)
|
||||||
r := big.NewInt(int64(prime.RandInt(0, int(pubK.N.Int64()))))
|
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)
|
c := new(big.Int).Mod(gMrN, n2)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decrypt deencrypts a ciphertext c with given PublicKey and PrivateKey
|
||||||
func Decrypt(c *big.Int, pubK PublicKey, privK PrivateKey) *big.Int {
|
func Decrypt(c *big.Int, pubK PublicKey, privK PrivateKey) *big.Int {
|
||||||
cLambda := new(big.Int).Exp(c, privK.Lambda, nil)
|
cLambda := new(big.Int).Exp(c, privK.Lambda, nil)
|
||||||
n2 := new(big.Int).Mul(pubK.N, pubK.N)
|
n2 := new(big.Int).Mul(pubK.N, pubK.N)
|
||||||
u := new(big.Int).Mod(cLambda, n2)
|
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)
|
LMu := new(big.Int).Mul(L, privK.Mu)
|
||||||
m := new(big.Int).Mod(LMu, pubK.N)
|
m := new(big.Int).Mod(LMu, pubK.N)
|
||||||
return m
|
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 {
|
func HomomorphicAddition(c1 *big.Int, c2 *big.Int, pubK PublicKey) *big.Int {
|
||||||
c1c2 := new(big.Int).Mul(c1, c2)
|
c1c2 := new(big.Int).Mul(c1, c2)
|
||||||
n2 := new(big.Int).Mul(pubK.N, pubK.N)
|
n2 := new(big.Int).Mul(pubK.N, pubK.N)
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ func TestEncryptDecrypt(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.Error())
|
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)
|
||||||
|
|||||||
@@ -3,21 +3,26 @@ package prime
|
|||||||
import "math/rand"
|
import "math/rand"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// MaxPrime is to get a prime value below this number
|
||||||
MaxPrime = 2000
|
MaxPrime = 2000
|
||||||
|
// MinPrime is to get a prime value above this number
|
||||||
MinPrime = 500
|
MinPrime = 500
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// RandInt returns a random integer between two values
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RandPrime returns a random prime number between two values
|
||||||
func RandPrime(min int, max int) int {
|
func RandPrime(min int, max int) int {
|
||||||
primes := SieveOfEratosthenes(max)
|
primes := SieveOfEratosthenes(max)
|
||||||
randN := rand.Intn(len(primes)-0) + 0
|
randN := rand.Intn(len(primes)-0) + 0
|
||||||
return primes[randN]
|
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) {
|
func SieveOfEratosthenes(N int) (primes []int) {
|
||||||
b := make([]bool, N)
|
b := make([]bool, N)
|
||||||
for i := 2; i < N; i++ {
|
for i := 2; i < N; i++ {
|
||||||
@@ -32,6 +37,7 @@ func SieveOfEratosthenes(N int) (primes []int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gcd returns the greatest common divisor
|
||||||
func Gcd(a, b int) int {
|
func Gcd(a, b int) int {
|
||||||
var bgcd func(a, b, res int) int
|
var bgcd func(a, b, res int) int
|
||||||
bgcd = func(a, b, res int) int {
|
bgcd = func(a, b, res int) int {
|
||||||
|
|||||||
25
rsa/rsa.go
25
rsa/rsa.go
@@ -12,24 +12,25 @@ const (
|
|||||||
|
|
||||||
var bigOne = big.NewInt(int64(1))
|
var bigOne = big.NewInt(int64(1))
|
||||||
|
|
||||||
|
// PublicKey stores the public key data
|
||||||
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"`
|
||||||
}
|
}
|
||||||
type PublicKeyString struct {
|
|
||||||
E string `json:"e"`
|
// PrivateKey stores the private key data
|
||||||
N string `json:"n"`
|
|
||||||
}
|
|
||||||
type PrivateKey struct {
|
type PrivateKey struct {
|
||||||
D *big.Int `json:"d"`
|
D *big.Int `json:"d"`
|
||||||
N *big.Int `json:"n"`
|
N *big.Int `json:"n"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Key stores the public and private key data
|
||||||
type Key struct {
|
type Key struct {
|
||||||
PubK PublicKey
|
PubK PublicKey
|
||||||
PrivK PrivateKey
|
PrivK PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateKeyPair generates a random private and public key
|
||||||
func GenerateKeyPair() (key Key, err error) {
|
func GenerateKeyPair() (key Key, err error) {
|
||||||
p, err := rand.Prime(rand.Reader, bits/2)
|
p, err := rand.Prime(rand.Reader, bits/2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -41,9 +42,9 @@ func GenerateKeyPair() (key Key, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
n := new(big.Int).Mul(p, q)
|
n := new(big.Int).Mul(p, q)
|
||||||
p_1 := new(big.Int).Sub(p, bigOne)
|
p1 := new(big.Int).Sub(p, bigOne)
|
||||||
q_1 := new(big.Int).Sub(q, bigOne)
|
q1 := new(big.Int).Sub(q, bigOne)
|
||||||
phi := new(big.Int).Mul(p_1, q_1)
|
phi := new(big.Int).Mul(p1, q1)
|
||||||
e := 65537
|
e := 65537
|
||||||
var pubK PublicKey
|
var pubK PublicKey
|
||||||
pubK.E = big.NewInt(int64(e))
|
pubK.E = big.NewInt(int64(e))
|
||||||
@@ -60,15 +61,19 @@ func GenerateKeyPair() (key Key, err error) {
|
|||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encrypt encrypts a message m with given PublicKey
|
||||||
func Encrypt(m *big.Int, pubK PublicKey) *big.Int {
|
func Encrypt(m *big.Int, pubK PublicKey) *big.Int {
|
||||||
c := new(big.Int).Exp(m, pubK.E, pubK.N)
|
c := new(big.Int).Exp(m, pubK.E, pubK.N)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decrypt deencrypts a ciphertext c with given PrivateKey
|
||||||
func Decrypt(c *big.Int, privK PrivateKey) *big.Int {
|
func Decrypt(c *big.Int, privK PrivateKey) *big.Int {
|
||||||
m := new(big.Int).Exp(c, privK.D, privK.N)
|
m := new(big.Int).Exp(c, privK.D, privK.N)
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Blind blinds a message
|
||||||
func Blind(m *big.Int, r *big.Int, pubK PublicKey) *big.Int {
|
func Blind(m *big.Int, r *big.Int, pubK PublicKey) *big.Int {
|
||||||
rE := new(big.Int).Exp(r, pubK.E, nil)
|
rE := new(big.Int).Exp(r, pubK.E, nil)
|
||||||
mrE := new(big.Int).Mul(m, rE)
|
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
|
return mBlinded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlindSign blind signs a message without knowing the content
|
||||||
func BlindSign(m *big.Int, privK PrivateKey) *big.Int {
|
func BlindSign(m *big.Int, privK PrivateKey) *big.Int {
|
||||||
sigma := new(big.Int).Exp(m, privK.D, privK.N)
|
sigma := new(big.Int).Exp(m, privK.D, privK.N)
|
||||||
return sigma
|
return sigma
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unblind unblinds the Blinded Signature
|
||||||
func Unblind(sigma *big.Int, r *big.Int, pubK PublicKey) *big.Int {
|
func Unblind(sigma *big.Int, r *big.Int, pubK PublicKey) *big.Int {
|
||||||
r1 := new(big.Int).ModInverse(r, pubK.N)
|
r1 := new(big.Int).ModInverse(r, pubK.N)
|
||||||
bsr := new(big.Int).Mul(sigma, r1)
|
bsr := new(big.Int).Mul(sigma, r1)
|
||||||
sig := new(big.Int).Mod(bsr, pubK.N)
|
sig := new(big.Int).Mod(bsr, pubK.N)
|
||||||
return sig
|
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 {
|
func Verify(msg *big.Int, mSigned *big.Int, pubK PublicKey) bool {
|
||||||
//decrypt the mSigned with pubK
|
//decrypt the mSigned with pubK
|
||||||
Cd := new(big.Int).Exp(mSigned, pubK.E, nil)
|
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())
|
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 {
|
func HomomorphicMul(c1 *big.Int, c2 *big.Int, pubK PublicKey) *big.Int {
|
||||||
c1c2 := new(big.Int).Mul(c1, c2)
|
c1c2 := new(big.Int).Mul(c1, c2)
|
||||||
n2 := new(big.Int).Mul(pubK.N, pubK.N)
|
n2 := new(big.Int).Mul(pubK.N, pubK.N)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package rsa
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -12,7 +11,6 @@ func TestEncryptDecrypt(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(err.Error())
|
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)
|
||||||
|
|||||||
45
secrets/secrets_test.go
Normal file
45
secrets/secrets_test.go
Normal file
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
114
secrets/sercrets.go
Normal file
114
secrets/sercrets.go
Normal file
@@ -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<p. k: " + k.String() + ", p: " + p.String())
|
||||||
|
}
|
||||||
|
//generate the basePolynomial
|
||||||
|
var basePolynomial []*big.Int
|
||||||
|
basePolynomial = append(basePolynomial, k)
|
||||||
|
for i := 0; i < int(t.Int64())-1; i++ {
|
||||||
|
randPrime, err := rand.Prime(rand.Reader, bits/2)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
basePolynomial = append(basePolynomial, randPrime)
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculate shares, based on the basePolynomial
|
||||||
|
var shares []*big.Int
|
||||||
|
for i := 1; i < int(n.Int64())+1; i++ {
|
||||||
|
var pResultMod *big.Int
|
||||||
|
pResult := big.NewInt(int64(0))
|
||||||
|
for x, polElem := range basePolynomial {
|
||||||
|
if x == 0 {
|
||||||
|
pResult = pResult.Add(pResult, polElem)
|
||||||
|
} else {
|
||||||
|
iBigInt := big.NewInt(int64(i))
|
||||||
|
xBigInt := big.NewInt(int64(x))
|
||||||
|
iPowed := iBigInt.Exp(iBigInt, xBigInt, nil)
|
||||||
|
currElem := iPowed.Mul(iPowed, polElem)
|
||||||
|
pResult = pResult.Add(pResult, currElem)
|
||||||
|
pResultMod = pResult.Mod(pResult, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shares = append(shares, pResultMod)
|
||||||
|
}
|
||||||
|
//put the share together with his p value
|
||||||
|
result = packSharesAndI(shares)
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func packSharesAndI(sharesString []*big.Int) (r [][]*big.Int) {
|
||||||
|
for i, share := range sharesString {
|
||||||
|
curr := []*big.Int{share, big.NewInt(int64(i + 1))}
|
||||||
|
r = append(r, curr)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
func unpackSharesAndI(sharesPacked [][]*big.Int) ([]*big.Int, []*big.Int) {
|
||||||
|
var shares []*big.Int
|
||||||
|
var i []*big.Int
|
||||||
|
for _, share := range sharesPacked {
|
||||||
|
shares = append(shares, share[0])
|
||||||
|
i = append(i, share[1])
|
||||||
|
}
|
||||||
|
return shares, i
|
||||||
|
}
|
||||||
|
|
||||||
|
// LagrangeInterpolation calculates the secret from given shares
|
||||||
|
func LagrangeInterpolation(sharesGiven [][]*big.Int, p *big.Int) *big.Int {
|
||||||
|
resultN := big.NewInt(int64(0))
|
||||||
|
resultD := big.NewInt(int64(0))
|
||||||
|
|
||||||
|
//unpack shares
|
||||||
|
sharesBigInt, sharesIBigInt := unpackSharesAndI(sharesGiven)
|
||||||
|
|
||||||
|
for i := 0; i < len(sharesBigInt); i++ {
|
||||||
|
lagrangeNumerator := big.NewInt(int64(1))
|
||||||
|
lagrangeDenominator := big.NewInt(int64(1))
|
||||||
|
for j := 0; j < len(sharesBigInt); j++ {
|
||||||
|
if sharesIBigInt[i] != sharesIBigInt[j] {
|
||||||
|
currLagrangeNumerator := sharesIBigInt[j]
|
||||||
|
currLagrangeDenominator := new(big.Int).Sub(sharesIBigInt[j], sharesIBigInt[i])
|
||||||
|
lagrangeNumerator = new(big.Int).Mul(lagrangeNumerator, currLagrangeNumerator)
|
||||||
|
lagrangeDenominator = new(big.Int).Mul(lagrangeDenominator, currLagrangeDenominator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
numerator := new(big.Int).Mul(sharesBigInt[i], lagrangeNumerator)
|
||||||
|
quo := new(big.Int).Quo(numerator, lagrangeDenominator)
|
||||||
|
if quo.Int64() != 0 {
|
||||||
|
resultN = resultN.Add(resultN, quo)
|
||||||
|
} else {
|
||||||
|
resultNMULlagrangeDenominator := new(big.Int).Mul(resultN, lagrangeDenominator)
|
||||||
|
resultN = new(big.Int).Add(resultNMULlagrangeDenominator, numerator)
|
||||||
|
|
||||||
|
resultD = resultD.Add(resultD, lagrangeDenominator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var modinvMul *big.Int
|
||||||
|
if resultD.Int64() != 0 {
|
||||||
|
modinv := new(big.Int).ModInverse(resultD, p)
|
||||||
|
modinvMul = new(big.Int).Mul(resultN, modinv)
|
||||||
|
} else {
|
||||||
|
modinvMul = resultN
|
||||||
|
}
|
||||||
|
r := new(big.Int).Mod(modinvMul, p)
|
||||||
|
return r
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user