|
1 | 1 | package crypto |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "crypto/aes" |
4 | 5 | "crypto/rand" |
| 6 | + "crypto/sha3" |
5 | 7 | "encoding/binary" |
6 | 8 | "math/big" |
7 | 9 | ) |
@@ -48,57 +50,41 @@ func NevilleInterpolation(xs []*big.Int, ys []*big.Int, x *big.Int, fieldOrder * |
48 | 50 | return result |
49 | 51 | } |
50 | 52 |
|
51 | | -// SharedSecretsGenerator computes a PRF-based generator from shared secrets and round number. |
52 | | -// The generator is used to derive deterministic pseudo-random values. |
53 | | -func SharedSecretsGenerator(sharedSecrets []SharedKey, round *big.Int, fieldOrder *big.Int) *big.Int { |
54 | | - el := new(big.Int) |
55 | | - secretElementGenerator := new(big.Int).Set(prfSeed) |
56 | | - for _, sse := range sharedSecrets { |
57 | | - // Probably insecure |
58 | | - el.SetBytes(sse) |
59 | | - el.Add(el, round) |
60 | | - el.Mul(el, prfSeed) |
61 | | - el.Mod(el, fieldOrder) |
62 | | - secretElementGenerator.Add(secretElementGenerator, el) |
63 | | - secretElementGenerator.Mod(secretElementGenerator, fieldOrder) |
64 | | - } |
65 | | - return secretElementGenerator |
66 | | -} |
67 | | - |
68 | | -// DeriveBlindingVector generates a vector of blinding factors from shared secrets. |
69 | | -// The blinding factors are deterministically derived for the given round and can be |
70 | | -// used to blind and unblind values in the ADCNet protocol. |
| 53 | +// DeriveBlindingVector deterministically generates a vector of blinding elements from shared secrets for the given round. |
71 | 54 | func DeriveBlindingVector(sharedSecrets []SharedKey, round uint32, nEls int32, fieldOrder *big.Int) []*big.Int { |
72 | | - buf := make([]big.Int, nEls) |
| 55 | + bytesPerElement := (fieldOrder.BitLen()+7)/8 |
| 56 | + srcBytesBuf := make([]byte, int(nEls)*bytesPerElement) |
| 57 | + dstBytesBuf := make([]byte, int(nEls)*bytesPerElement) |
| 58 | + elBuf := make([]big.Int, nEls) |
73 | 59 | res := make([]*big.Int, nEls) |
74 | 60 | for i := range res { |
75 | | - res[i] = &buf[i] |
| 61 | + res[i] = &elBuf[i] |
76 | 62 | } |
77 | 63 |
|
78 | | - bigRound := big.NewInt(int64(round)) |
| 64 | + // Assumes all shared secrets are the same length |
| 65 | + roundKeyBuf := make([]byte, 4+len(sharedSecrets[0])) |
| 66 | + binary.BigEndian.PutUint32(roundKeyBuf[:4], uint32(round)) |
79 | 67 |
|
80 | | - secretElementGenerator := SharedSecretsGenerator(sharedSecrets, bigRound, fieldOrder) |
81 | | - // Note: we can chunk and parallelize. Be careful with the generator though. |
82 | | - DeriveBlindingVectorInplace(res, secretElementGenerator, bigRound, 0, len(res), fieldOrder) |
83 | | - return res |
84 | | -} |
| 68 | + workingEl := big.NewInt(0) |
| 69 | + |
| 70 | + for _, sharedSecret := range sharedSecrets { |
| 71 | + copy(roundKeyBuf[4:], sharedSecret) |
| 72 | + roundSharedKey := sha3.Sum256(roundKeyBuf) |
85 | 73 |
|
86 | | -// DeriveBlindingVectorInplace computes blinding factors in-place for a range of indices. |
87 | | -// This is used internally by DeriveBlindingVector and can be parallelized by chunking. |
88 | | -func DeriveBlindingVectorInplace(res []*big.Int, secretElementGenerator *big.Int, round *big.Int, start int, end int, fieldOrder *big.Int) { |
89 | | - nonceBuf := make([]byte, 8) |
90 | | - binary.BigEndian.PutUint32(nonceBuf, uint32(round.Int64())) |
91 | | - nonce := new(big.Int) |
92 | | - el := new(big.Int).Exp(secretElementGenerator, big.NewInt(int64(start)), fieldOrder) |
93 | | - |
94 | | - for i := start; i < end; i++ { |
95 | | - binary.BigEndian.PutUint32(nonceBuf[4:], uint32(i)) |
96 | | - nonce.SetBytes(nonceBuf) |
97 | | - res[i].Mul(res[i], nonce.Mod(nonce, nonce.Mul(nonce, prfSeed))) |
98 | | - res[i].Mod(res[i], fieldOrder) |
99 | | - el.Mul(el, secretElementGenerator) |
100 | | - el.Mod(el, fieldOrder) |
| 74 | + block, err := aes.NewCipher(roundSharedKey[:]) |
| 75 | + if err != nil { |
| 76 | + panic(err.Error()) |
| 77 | + } |
| 78 | + |
| 79 | + block.Encrypt(dstBytesBuf, srcBytesBuf) |
| 80 | + |
| 81 | + for i := 0; i < int(nEls); i++ { |
| 82 | + workingEl.SetBytes(dstBytesBuf[i*bytesPerElement:(i+1)*bytesPerElement]) |
| 83 | + FieldAddInplace(res[i], workingEl, fieldOrder) |
| 84 | + } |
101 | 85 | } |
| 86 | + |
| 87 | + return res |
102 | 88 | } |
103 | 89 |
|
104 | 90 | // RandomPolynomialEvals generates a random polynomial of given degree that evaluates |
|
0 commit comments