in client/internal/secret_sharing/internal/shamirgeneric/shamir_generic.go [27:76]
func SplitSecret(metadata secrets.Metadata, secret []byte, gf field.GaloisField) (secrets.Split, error) {
if err := validateSplitInput(metadata, secret, gf); err != nil {
return secrets.Split{}, err
}
threshold := metadata.Threshold
numShares := metadata.NumShares
// The `secret` can be an arbitrary length byte array, but each element in a field is of
// a finite size, hence the `secret` is split into a set of elements in the field.
subsecrets := gf.DecodeElements(secret)
shares := make([]secrets.Share, numShares)
// For each subsecret we build a polynomial of degree N, where N is `threshold`.
// Each subsecret is the constant coefficient in the polynomial and every other coefficient
// is selected as a random field element:
// subsecret + R_1 * x^1 + R_2 * X^2 + ... + R_N * X^N
for _, subsecret := range subsecrets {
coefficients := make([]field.Element, threshold, threshold)
coefficients[0] = subsecret
for i := 1; i < threshold; i++ {
var err error
if coefficients[i], err = gf.NewRandomNonZero(); err != nil {
return secrets.Split{}, err
}
}
for i := 0; i < numShares; i++ {
// We create each sub-share by evaluating each polynomial for a subsecret
// at a specific value `X`, this gives us the point (X, Y).
xi, err := gf.CreateElement(i + 1)
if err != nil {
return secrets.Split{}, err
}
subshare, err := evaluatePolynomial(coefficients, xi, gf)
if err != nil {
return secrets.Split{}, err
}
// shares is a set of encoded field elements. Each field element is the evaluation of a
// different polynomial where the constant term of each polynomial represents a subsecrets.
// shares[0] = [ F1(1), F2(1), ..., FN(1) ]
// shares[1] = [ F1(2), F2(2), ..., FN(2) ]
// shares[N - 1] = [ F1(N), F2(N), ..., FN(N) ]
shares[i].Value = append(shares[i].Value, subshare.Bytes()...)
shares[i].X = i + 1
}
}
return secrets.Split{
Shares: shares,
Metadata: metadata,
SecretLen: len(secret),
}, nil
}