// GenerateKeyPair returns a private/public key pair. The private key is // generated using the given reader, which must return random data. The // receiver side of the key exchange (aka "Bob") MUST use KeyExchangeBob() // instead of this routine. func GenerateKeyPair(rand io.Reader) (*PrivateKeyAlice, *PublicKeyAlice, error) { var a, e, pk, r poly var seed, noiseSeed [SeedBytes]byte // seed <- Sample({0, 1}^256) if _, err := io.ReadFull(rand, seed[:]); err != nil { return nil, nil, err } seed = sha3.Sum256(seed[:]) // Don't send output of system RNG. // a <- Parse(SHAKE-128(seed)) a.uniform(&seed, TorSampling) // s, e <- Sample(psi(n, 12)) if _, err := io.ReadFull(rand, noiseSeed[:]); err != nil { return nil, nil, err } defer memwipe(noiseSeed[:]) privKey := new(PrivateKeyAlice) privKey.sk.getNoise(&noiseSeed, 0) privKey.sk.ntt() e.getNoise(&noiseSeed, 1) e.ntt() // b <- as + e pubKey := new(PublicKeyAlice) r.pointwise(&privKey.sk, &a) pk.add(&e, &r) encodeA(pubKey.Send[:], &pk, &seed) return privKey, pubKey, nil }
func (v *Verifier) VerifySpace(challenges []int64, hashes [][]byte, parents [][][]byte, proofs [][][]byte, pProofs [][][][]byte) bool { for i := range challenges { buf := make([]byte, hashSize) binary.PutVarint(buf, challenges[i]+v.pow2) val := append(v.pk, buf...) for _, ph := range parents[i] { val = append(val, ph...) } exp := sha3.Sum256(val) for j := range exp { if exp[j] != hashes[i][j] { return false } } if !v.Verify(challenges[i], hashes[i], proofs[i]) { return false } ps := v.graph.GetParents(challenges[i], v.index) for j := range ps { if !v.Verify(ps[j], parents[i][j], pProofs[i][j]) { return false } } } return true }
// Iterative function to generate merkle tree // Should have at most O(lgn) hashes in memory at a time // return: the root hash func (p *Prover) generateMerkle() []byte { var stack []int64 var hashStack [][]byte cur := int64(1) count := int64(1) for count == 1 || len(stack) != 0 { empty := p.emptyMerkle(cur) for ; cur < 2*p.pow2 && !empty; cur *= 2 { if cur < p.pow2 { //right child stack = append(stack, 2*cur+1) } stack = append(stack, cur) } if empty { count += p.graph.subtree(cur) hashStack = append(hashStack, make([]byte, hashSize)) } cur, stack = stack[len(stack)-1], stack[:len(stack)-1] if len(stack) > 0 && cur < p.pow2 && (stack[len(stack)-1] == 2*cur+1) { stack = stack[:len(stack)-1] stack = append(stack, cur) cur = 2*cur + 1 continue } if cur >= p.pow2 { if cur >= p.pow2+p.size { hashStack = append(hashStack, make([]byte, hashSize)) count++ } else { n := p.graph.GetId(count) count++ hashStack = append(hashStack, n.H) } } else if !p.emptyMerkle(cur) { hash2 := hashStack[len(hashStack)-1] hashStack = hashStack[:len(hashStack)-1] hash1 := hashStack[len(hashStack)-1] hashStack = hashStack[:len(hashStack)-1] val := append(hash1[:], hash2[:]...) hash := sha3.Sum256(val) hashStack = append(hashStack, hash[:]) p.graph.NewNodeById(count, hash[:]) count++ } cur = 2 * p.pow2 } return hashStack[0] }
// Compute quality of the answer. Also builds a verifier // return: quality in float64 func (c *Client) Quality(challenge []byte, a block.Answer) float64 { nodes := c.verifier.SelectChallenges(challenge) if !c.verifier.VerifySpace(nodes, a.Hashes, a.Parents, a.Proofs, a.PProofs) { return -1 } all := util.Concat(a.Hashes) answerHash := sha3.Sum256(all) x := new(big.Float).SetInt(new(big.Int).SetBytes(answerHash[:])) num, _ := util.Root(x, a.Size).Float64() den := math.Exp2(float64(1<<8) / float64(a.Size)) return num / den }
// KeyExchangeBob is the Responder side of the Ring-LWE key exchange. The // shared secret and "public key" (key + reconciliation data) are generated // using the given reader, which must return random data. func KeyExchangeBob(rand io.Reader, alicePk *PublicKeyAlice) (*PublicKeyBob, []byte, error) { var pka, a, sp, ep, u, v, epp, r poly var seed, noiseSeed [SeedBytes]byte if _, err := io.ReadFull(rand, noiseSeed[:]); err != nil { return nil, nil, err } defer memwipe(noiseSeed[:]) // a <- Parse(SHAKE-128(seed)) decodeA(&pka, &seed, alicePk.Send[:]) a.uniform(&seed, TorSampling) // s', e', e'' <- Sample(psi(n, 12)) sp.getNoise(&noiseSeed, 0) sp.ntt() ep.getNoise(&noiseSeed, 1) ep.ntt() epp.getNoise(&noiseSeed, 2) // u <- as' + e' u.pointwise(&a, &sp) u.add(&u, &ep) // v <- bs' + e'' v.pointwise(&pka, &sp) v.invNtt() v.add(&v, &epp) // r <- Sample(HelpRec(v)) r.helpRec(&v, &noiseSeed, 3) pubKey := new(PublicKeyBob) encodeB(pubKey.Send[:], &u, &r) // nu <- Rec(v, r) var nu [SharedSecretSize]byte rec(&nu, &v, &r) // mu <- SHA3-256(nu) mu := sha3.Sum256(nu[:]) // Scrub the sensitive stuff... memwipe(nu[:]) sp.reset() v.reset() return pubKey, mu[:], nil }
// Generate challenge from older blocks // return: challenge for next block []byte func (c *Client) GenerateChallenge() []byte { var b *block.Block var err error if c.chain.LastBlock < c.dist { b, err = c.chain.Read(c.chain.LastBlock) } else { b, err = c.chain.Read(c.chain.LastBlock - (c.dist - 1)) } if err != nil { panic(err) } bin, err := b.MarshalBinary() if err != nil { panic(err) } challenge := sha3.Sum256(bin) return challenge[:] }
func NewBlock(old *Block, prf PoS, ts []Transaction, signer crypto.Signer) *Block { oldH, err := old.Hash.MarshalBinary() if err != nil { panic(err) } prevHash := sha3.Sum256(oldH) h := Hash{ Hash: prevHash[:], Proof: prf, } var tsBytes []byte for i := range ts { b, err := ts[i].MarshalBinary() if err != nil { panic(err) } tsBytes = append(tsBytes, b...) } sigBytes := util.Concat([][]byte{old.Sig.Tsig, old.Sig.Ssig}) tsig, err := signer.Sign(rand.Reader, tsBytes, crypto.SHA3_256) if err != nil { panic(err) } ssig, err := signer.Sign(rand.Reader, sigBytes, crypto.SHA3_256) if err != nil { panic(err) } sig := Signature{ Tsig: tsig, Ssig: ssig, } b := Block{ Id: old.Id + 1, Hash: h, Trans: ts, Sig: sig, } return &b }
func (v *Verifier) Verify(node int64, hash []byte, proof [][]byte) bool { curHash := hash counter := 0 for i := node + v.pow2; i > 1; i /= 2 { var val []byte if i%2 == 0 { val = append(curHash, proof[counter]...) } else { val = append(proof[counter], curHash...) } hash := sha3.Sum256(val) curHash = hash[:] counter++ } for i := range v.root { if v.root[i] != curHash[i] { return false } } return len(v.root) == len(curHash) }
// KeyExchangeAlice is the Initiaitor side of the Ring-LWE key exchange. The // provided private key is obliterated prior to returning, to promote // implementing Perfect Forward Secrecy. func KeyExchangeAlice(bobPk *PublicKeyBob, aliceSk *PrivateKeyAlice) ([]byte, error) { var u, r, vp poly decodeB(&u, &r, bobPk.Send[:]) // v' <- us vp.pointwise(&aliceSk.sk, &u) vp.invNtt() // nu <- Rec(v', r) var nu [SharedSecretSize]byte rec(&nu, &vp, &r) // mu <- Sha3-256(nu) mu := sha3.Sum256(nu[:]) // Scrub the sensitive stuff... memwipe(nu[:]) vp.reset() aliceSk.Reset() return mu[:], nil }
func (g *Graph) ButterflyGraph(index int64, count *int64) { if index == 0 { index = 1 } numLevel := 2 * index perLevel := int64(1 << uint64(index)) begin := *count - perLevel // level 0 created outside // no parents at level 0 var level, i int64 for level = 1; level < numLevel; level++ { for i = 0; i < perLevel; i++ { var prev int64 shift := index - level if level > numLevel/2 { shift = level - numLevel/2 } if (i>>uint64(shift))&1 == 0 { prev = i + (1 << uint64(shift)) } else { prev = i - (1 << uint64(shift)) } parent0 := g.GetNode(begin + (level-1)*perLevel + prev) parent1 := g.GetNode(*count - perLevel) ph := append(parent0.H, parent1.H...) buf := make([]byte, hashSize) binary.PutVarint(buf, *count) val := append(g.pk, buf...) val = append(val, ph...) hash := sha3.Sum256(val) g.NewNode(*count, hash[:]) *count++ } } }
// hash_string hashes a string func hash_string(key string) string { hash := sha3.Sum256([]byte(key)) return base64.StdEncoding.EncodeToString(hash[:]) }
func (g *Graph) XiGraph(index int64, count *int64) { // recursively generate graphs // compute hashes along the way pow2index := int64(1 << uint64(index)) // the first sources // if index == 1, then this will generate level 0 of the butterfly var i int64 if *count == g.pow2 { for i = 0; i < pow2index; i++ { buf := make([]byte, hashSize) binary.PutVarint(buf, *count) val := append(g.pk, buf...) hash := sha3.Sum256(val) g.NewNode(*count, hash[:]) *count++ } } if index == 1 { g.ButterflyGraph(index, count) return } sources := *count - pow2index firstButter := sources + pow2index firstXi := firstButter + numButterfly(index-1) secondXi := firstXi + numXi(index-1) secondButter := secondXi + numXi(index-1) sinks := secondButter + numButterfly(index-1) pow2index_1 := int64(1 << uint64(index-1)) // sources to sources of first butterfly // create sources of first butterly for i = 0; i < pow2index_1; i++ { parent0 := g.GetNode(sources + i) parent1 := g.GetNode(sources + i + pow2index_1) ph := append(parent0.H, parent1.H...) buf := make([]byte, hashSize) binary.PutVarint(buf, *count) val := append(g.pk, buf...) val = append(val, ph...) hash := sha3.Sum256(val) g.NewNode(*count, hash[:]) *count++ } g.ButterflyGraph(index-1, count) // sinks of first butterfly to sources of first xi graph for i = 0; i < pow2index_1; i++ { nodeId := firstXi + i parent := g.GetNode(firstXi - pow2index_1 + i) buf := make([]byte, hashSize) binary.PutVarint(buf, nodeId) val := append(g.pk, buf...) val = append(val, parent.H...) hash := sha3.Sum256(val) g.NewNode(nodeId, hash[:]) *count++ } g.XiGraph(index-1, count) // sinks of first xi to sources of second xi for i = 0; i < pow2index_1; i++ { nodeId := secondXi + i parent := g.GetNode(secondXi - pow2index_1 + i) buf := make([]byte, hashSize) binary.PutVarint(buf, nodeId) val := append(g.pk, buf...) val = append(val, parent.H...) hash := sha3.Sum256(val) g.NewNode(nodeId, hash[:]) *count++ } g.XiGraph(index-1, count) // sinks of second xi to sources of second butterfly for i = 0; i < pow2index_1; i++ { nodeId := secondButter + i parent := g.GetNode(secondButter - pow2index_1 + i) buf := make([]byte, hashSize) binary.PutVarint(buf, nodeId) val := append(g.pk, buf...) val = append(val, parent.H...) hash := sha3.Sum256(val) g.NewNode(nodeId, hash[:]) *count++ } // generate sinks // sinks of second butterfly to sinks // and sources to sinks directly g.ButterflyGraph(index-1, count) for i = 0; i < pow2index_1; i++ { nodeId0 := sinks + i nodeId1 := sinks + i + pow2index_1 parent0 := g.GetNode(sinks - pow2index_1 + i) parent1_0 := g.GetNode(sources + i) parent1_1 := g.GetNode(sources + i + pow2index_1) ph := append(parent0.H, parent1_0.H...) buf := make([]byte, hashSize) binary.PutVarint(buf, nodeId0) val := append(g.pk, buf...) val = append(val, ph...) hash1 := sha3.Sum256(val) ph = append(parent0.H, parent1_1.H...) binary.PutVarint(buf, nodeId1) val = append(g.pk, buf...) val = append(val, ph...) hash2 := sha3.Sum256(val) g.NewNode(nodeId0, hash1[:]) g.NewNode(nodeId1, hash2[:]) *count += 2 } }
// Iterative generation of the graph func (g *Graph) XiGraphIter(index int64) { count := g.pow2 stack := []int64{index, index, index, index, index} graphStack := []int{4, 3, 2, 1, 0} var i int64 graph := 0 pow2index := int64(1 << uint64(index)) for i = 0; i < pow2index; i++ { //sources at this level buf := make([]byte, hashSize) binary.PutVarint(buf, count) val := append(g.pk, buf...) hash := sha3.Sum256(val) g.NewNode(count, hash[:]) count++ } if index == 1 { g.ButterflyGraph(index, &count) return } for len(stack) != 0 && len(graphStack) != 0 { index, stack = stack[len(stack)-1], stack[:len(stack)-1] graph, graphStack = graphStack[len(graphStack)-1], graphStack[:len(graphStack)-1] indices := []int64{index - 1, index - 1, index - 1, index - 1, index - 1} graphs := []int{4, 3, 2, 1, 0} pow2index := int64(1 << uint64(index)) pow2index_1 := int64(1 << uint64(index-1)) if graph == 0 { sources := count - pow2index // sources to sources of first butterfly // create sources of first butterly for i = 0; i < pow2index_1; i++ { parent0 := g.GetNode(sources + i) parent1 := g.GetNode(sources + i + pow2index_1) ph := append(parent0.H, parent1.H...) buf := make([]byte, hashSize) binary.PutVarint(buf, count) val := append(g.pk, buf...) val = append(val, ph...) hash := sha3.Sum256(val) g.NewNode(count, hash[:]) count++ } } else if graph == 1 { firstXi := count // sinks of first butterfly to sources of first xi graph for i = 0; i < pow2index_1; i++ { nodeId := firstXi + i // index is the last level; i.e., sinks parent := g.GetNode(firstXi - pow2index_1 + i) buf := make([]byte, hashSize) binary.PutVarint(buf, nodeId) val := append(g.pk, buf...) val = append(val, parent.H...) hash := sha3.Sum256(val) g.NewNode(nodeId, hash[:]) count++ } } else if graph == 2 { secondXi := count // sinks of first xi to sources of second xi for i = 0; i < pow2index_1; i++ { nodeId := secondXi + i parent := g.GetNode(secondXi - pow2index_1 + i) buf := make([]byte, hashSize) binary.PutVarint(buf, nodeId) val := append(g.pk, buf...) val = append(val, parent.H...) hash := sha3.Sum256(val) g.NewNode(nodeId, hash[:]) count++ } } else if graph == 3 { secondButter := count // sinks of second xi to sources of second butterfly for i = 0; i < pow2index_1; i++ { nodeId := secondButter + i parent := g.GetNode(secondButter - pow2index_1 + i) buf := make([]byte, hashSize) binary.PutVarint(buf, nodeId) val := append(g.pk, buf...) val = append(val, parent.H...) hash := sha3.Sum256(val) g.NewNode(nodeId, hash[:]) count++ } } else { sinks := count sources := sinks + pow2index - numXi(index) for i = 0; i < pow2index_1; i++ { nodeId0 := sinks + i nodeId1 := sinks + i + pow2index_1 parent0 := g.GetNode(sinks - pow2index_1 + i) parent1_0 := g.GetNode(sources + i) parent1_1 := g.GetNode(sources + i + pow2index_1) ph := append(parent0.H, parent1_0.H...) buf := make([]byte, hashSize) binary.PutVarint(buf, nodeId0) val := append(g.pk, buf...) val = append(val, ph...) hash1 := sha3.Sum256(val) ph = append(parent0.H, parent1_1.H...) binary.PutVarint(buf, nodeId1) val = append(g.pk, buf...) val = append(val, ph...) hash2 := sha3.Sum256(val) g.NewNode(nodeId0, hash1[:]) g.NewNode(nodeId1, hash2[:]) count += 2 } } if (graph == 0 || graph == 3) || ((graph == 1 || graph == 2) && index == 2) { g.ButterflyGraph(index-1, &count) } else if graph == 1 || graph == 2 { stack = append(stack, indices...) graphStack = append(graphStack, graphs...) } } }
func Sum256(password string) string { buf := []byte(password) hash := sha3.Sum256(buf) return string(hash[:]) }