// secrets is called after the handshake is completed. // It extracts the connection secrets from the handshake values. func (h *encHandshake) secrets(auth, authResp []byte) (secrets, error) { ecdheSecret, err := h.randomPrivKey.GenerateShared(h.remoteRandomPub, sskLen, sskLen) if err != nil { return secrets{}, err } // derive base secrets from ephemeral key agreement sharedSecret := crypto.Sha3(ecdheSecret, crypto.Sha3(h.respNonce, h.initNonce)) aesSecret := crypto.Sha3(ecdheSecret, sharedSecret) s := secrets{ RemoteID: h.remoteID, AES: aesSecret, MAC: crypto.Sha3(ecdheSecret, aesSecret), Token: crypto.Sha3(sharedSecret), } // setup sha3 instances for the MACs mac1 := sha3.NewKeccak256() mac1.Write(xor(s.MAC, h.respNonce)) mac1.Write(auth) mac2 := sha3.NewKeccak256() mac2.Write(xor(s.MAC, h.initNonce)) mac2.Write(authResp) if h.initiator { s.EgressMAC, s.IngressMAC = mac1, mac2 } else { s.EgressMAC, s.IngressMAC = mac2, mac1 } return s, nil }
func decodePacket(buf []byte) (packet, NodeID, []byte, error) { if len(buf) < headSize+1 { return nil, NodeID{}, nil, errPacketTooSmall } hash, sig, sigdata := buf[:macSize], buf[macSize:headSize], buf[headSize:] shouldhash := crypto.Sha3(buf[macSize:]) if !bytes.Equal(hash, shouldhash) { return nil, NodeID{}, nil, errBadHash } fromID, err := recoverNodeID(crypto.Sha3(buf[headSize:]), sig) if err != nil { return nil, NodeID{}, hash, err } var req packet switch ptype := sigdata[0]; ptype { case pingPacket: req = new(ping) case pongPacket: req = new(pong) case findnodePacket: req = new(findnode) case neighborsPacket: req = new(neighbors) default: return nil, fromID, hash, fmt.Errorf("unknown type: %d", ptype) } err = rlp.DecodeBytes(sigdata[1:], req) return req, fromID, hash, err }
func TestNatspecE2E(t *testing.T) { t.Skip() tf := testInit(t) defer tf.ethereum.Stop() resolver.CreateContracts(tf.xeth, testAccount) t.Logf("URLHint contract registered at %v", resolver.URLHintContractAddress) t.Logf("HashReg contract registered at %v", resolver.HashRegContractAddress) tf.applyTxs() ioutil.WriteFile("/tmp/"+testFileName, []byte(testDocs), os.ModePerm) dochash := common.BytesToHash(crypto.Sha3([]byte(testDocs))) codehex := tf.xeth.CodeAt(resolver.HashRegContractAddress) codehash := common.BytesToHash(crypto.Sha3(common.Hex2Bytes(codehex[2:]))) tf.setOwner() tf.registerNatSpec(codehash, dochash) tf.registerURL(dochash, "file:///"+testFileName) tf.applyTxs() chash, err := tf.testResolver().KeyToContentHash(codehash) if err != nil { t.Errorf("Can't find content hash") } t.Logf("chash = %x err = %v", chash, err) url, err2 := tf.testResolver().ContentHashToUrl(dochash) if err2 != nil { t.Errorf("Can't find URL hint") } t.Logf("url = %v err = %v", url, err2) // NatSpec info for register method of HashReg contract installed // now using the same transactions to check confirm messages tf.makeNatSpec = true tf.registerNatSpec(codehash, dochash) t.Logf("Confirm message: %v\n", tf.lastConfirm) if tf.lastConfirm != testExpNotice { t.Errorf("Wrong confirm message, expected '%v', got '%v'", testExpNotice, tf.lastConfirm) } tf.setOwner() t.Logf("Confirm message for unknown method: %v\n", tf.lastConfirm) if tf.lastConfirm != testExpNotice2 { t.Errorf("Wrong confirm message, expected '%v', got '%v'", testExpNotice2, tf.lastConfirm) } tf.registerURL(dochash, "file:///test.content") t.Logf("Confirm message for unknown contract: %v\n", tf.lastConfirm) if tf.lastConfirm != testExpNotice3 { t.Errorf("Wrong confirm message, expected '%v', got '%v'", testExpNotice3, tf.lastConfirm) } }
// sha3 returns the canonical sha3 of the 32byte (padded) input func sha3(in ...[]byte) []byte { out := make([]byte, len(in)*32) for i, input := range in { copy(out[i*32:i*32+32], common.LeftPadBytes(input, 32)) } return crypto.Sha3(out) }
func (self *DocServer) GetAuthContent(uri string, hash common.Hash) (content []byte, err error) { // retrieve content resp, err := self.Client().Get(uri) defer func() { if resp != nil { resp.Body.Close() } }() if err != nil { return } content, err = ioutil.ReadAll(resp.Body) if err != nil { return } // check hash to authenticate content hashbytes := crypto.Sha3(content) var chash common.Hash copy(chash[:], hashbytes) if chash != hash { content = nil err = fmt.Errorf("content hash mismatch") } return }
// sets defaults on the config func setDefaults(cfg *Config) { if cfg.Difficulty == nil { cfg.Difficulty = new(big.Int) } if cfg.Time == nil { cfg.Time = big.NewInt(time.Now().Unix()) } if cfg.GasLimit == nil { cfg.GasLimit = new(big.Int).Set(common.MaxBig) } if cfg.GasPrice == nil { cfg.GasPrice = new(big.Int) } if cfg.Value == nil { cfg.Value = new(big.Int) } if cfg.BlockNumber == nil { cfg.BlockNumber = new(big.Int) } if cfg.GetHashFn == nil { cfg.GetHashFn = func(n uint64) common.Hash { return common.BytesToHash(crypto.Sha3([]byte(new(big.Int).SetUint64(n).String()))) } } }
// also called by admin.contractInfo.get func FetchDocsForContract(contractAddress string, xeth *xeth.XEth, http *docserver.DocServer) (content []byte, err error) { // retrieve contract hash from state codehex := xeth.CodeAt(contractAddress) codeb := xeth.CodeAtBytes(contractAddress) if codehex == "0x" { err = fmt.Errorf("contract (%v) not found", contractAddress) return } codehash := common.BytesToHash(crypto.Sha3(codeb)) // set up nameresolver with natspecreg + urlhint contract addresses res := resolver.New(xeth) // resolve host via HashReg/UrlHint Resolver uri, hash, err := res.KeyToUrl(codehash) if err != nil { return } // get content via http client and authenticate content using hash content, err = http.GetAuthContent(uri, hash) if err != nil { return } return }
func TestGetAuthContent(t *testing.T) { text := "test" hash := common.Hash{} copy(hash[:], crypto.Sha3([]byte(text))) ioutil.WriteFile("/tmp/test.content", []byte(text), os.ModePerm) ds := New("/tmp/") content, err := ds.GetAuthContent("file:///test.content", hash) if err != nil { t.Errorf("no error expected, got %v", err) } if string(content) != text { t.Errorf("incorrect content. expected %v, got %v", text, string(content)) } hash = common.Hash{} content, err = ds.GetAuthContent("file:///test.content", hash) expected := "content hash mismatch 0000000000000000000000000000000000000000000000000000000000000000 != 9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658 (exp)" if err == nil { t.Errorf("expected error, got nothing") } else { if err.Error() != expected { t.Errorf("expected error '%s' got '%v'", expected, err) } } }
func storageMapping(addr, key []byte) []byte { data := make([]byte, 64) copy(data[0:32], key[0:32]) copy(data[32:64], addr[0:32]) sha := crypto.Sha3(data) return sha }
func ecrecoverFunc(in []byte) []byte { in = common.RightPadBytes(in, 128) // "in" is (hash, v, r, s), each 32 bytes // but for ecrecover we want (r, s, v) r := common.BytesToBig(in[64:96]) s := common.BytesToBig(in[96:128]) // Treat V as a 256bit integer vbig := common.Bytes2Big(in[32:64]) v := byte(vbig.Uint64()) if !crypto.ValidateSignatureValues(v, r, s) { glog.V(logger.Error).Infof("EC RECOVER FAIL: v, r or s value invalid") return nil } // v needs to be at the end and normalized for libsecp256k1 vbignormal := new(big.Int).Sub(vbig, big.NewInt(27)) vnormal := byte(vbignormal.Uint64()) rsv := append(in[64:128], vnormal) pubKey, err := crypto.Ecrecover(in[:32], rsv) // make sure the public key is a valid one if err != nil { glog.V(logger.Error).Infof("EC RECOVER FAIL: ", err) return nil } // the first byte of pubkey is bitcoin heritage return common.LeftPadBytes(crypto.Sha3(pubKey[1:])[12:], 32) }
func ecrecoverFunc(in []byte) []byte { // "in" is (hash, v, r, s), each 32 bytes // but for ecrecover we want (r, s, v) if len(in) < ecRecoverInputLength { return nil } // Treat V as a 256bit integer v := new(big.Int).Sub(common.Bytes2Big(in[32:64]), big.NewInt(27)) // Ethereum requires V to be either 0 or 1 => (27 || 28) if !(v.Cmp(Zero) == 0 || v.Cmp(One) == 0) { return nil } // v needs to be moved to the end rsv := append(in[64:128], byte(v.Uint64())) pubKey, err := crypto.Ecrecover(in[:32], rsv) // make sure the public key is a valid one if err != nil { glog.V(logger.Error).Infof("EC RECOVER FAIL: ", err) return nil } // the first byte of pubkey is bitcoin heritage return common.LeftPadBytes(crypto.Sha3(pubKey[1:])[12:], 32) }
// Tests that at any point in time during a sync, only complete sub-tries are in // the database. func TestIncompleteStateSync(t *testing.T) { // Create a random state to copy srcDb, srcRoot, srcAccounts := makeTestState() // Create a destination state and sync with the scheduler dstDb, _ := ethdb.NewMemDatabase() sched := NewStateSync(srcRoot, dstDb) added := []common.Hash{} queue := append([]common.Hash{}, sched.Missing(1)...) for len(queue) > 0 { // Fetch a batch of state nodes results := make([]trie.SyncResult, len(queue)) for i, hash := range queue { data, err := srcDb.Get(hash.Bytes()) if err != nil { t.Fatalf("failed to retrieve node data for %x: %v", hash, err) } results[i] = trie.SyncResult{Hash: hash, Data: data} } // Process each of the state nodes if index, err := sched.Process(results); err != nil { t.Fatalf("failed to process result #%d: %v", index, err) } for _, result := range results { added = append(added, result.Hash) } // Check that all known sub-tries in the synced state is complete for _, root := range added { // Skim through the accounts and make sure the root hash is not a code node codeHash := false for _, acc := range srcAccounts { if bytes.Compare(root.Bytes(), crypto.Sha3(acc.code)) == 0 { codeHash = true break } } // If the root is a real trie node, check consistency if !codeHash { if err := checkStateConsistency(dstDb, root); err != nil { t.Fatalf("state inconsistent: %v", err) } } } // Fetch the next batch to retrieve queue = append(queue[:0], sched.Missing(1)...) } // Sanity check that removing any node from the database is detected for _, node := range added[1:] { key := node.Bytes() value, _ := dstDb.Get(key) dstDb.Delete(key) if err := checkStateConsistency(dstDb, added[0]); err == nil { t.Fatalf("trie inconsistency not caught, missing: %x", key) } dstDb.Put(key, value) } }
// Calculates the sha3 over req.Params.Data func (self *web3Api) Sha3(req *shared.Request) (interface{}, error) { args := new(Sha3Args) if err := self.codec.Decode(req.Params, &args); err != nil { return nil, err } return common.ToHex(crypto.Sha3(common.FromHex(args.Data))), nil }
func TestEmptyTrie(t *testing.T) { trie := NewEmpty() res := trie.Hash() exp := crypto.Sha3(common.Encode("")) if !bytes.Equal(res, exp) { t.Errorf("expected %x got %x", exp, res) } }
func SaveInfo(info *ContractInfo, filename string) (contenthash common.Hash, err error) { infojson, err := json.Marshal(info) if err != nil { return } contenthash = common.BytesToHash(crypto.Sha3(infojson)) err = ioutil.WriteFile(filename, infojson, 0600) return }
func ExtractInfo(contract *Contract, filename string) (contenthash common.Hash, err error) { contractInfo, err := json.Marshal(contract.Info) if err != nil { return } contenthash = common.BytesToHash(crypto.Sha3(contractInfo)) err = ioutil.WriteFile(filename, contractInfo, 0600) return }
func New(xeth *xeth.XEth, tx string, http *docserver.DocServer) (self *NatSpec, err error) { // extract contract address from tx var obj map[string]json.RawMessage err = json.Unmarshal([]byte(tx), &obj) if err != nil { return } var tmp []map[string]string err = json.Unmarshal(obj["params"], &tmp) if err != nil { return } contractAddress := tmp[0]["to"] // retrieve contract hash from state if !xeth.IsContract(contractAddress) { err = fmt.Errorf("NatSpec error: contract not found") return } codehex := xeth.CodeAt(contractAddress) codeHash := common.BytesToHash(crypto.Sha3(common.Hex2Bytes(codehex[2:]))) // parse out host/domain // set up nameresolver with natspecreg + urlhint contract addresses res := resolver.New( xeth, resolver.URLHintContractAddress, resolver.HashRegContractAddress, ) // resolve host via HashReg/UrlHint Resolver uri, hash, err := res.KeyToUrl(codeHash) if err != nil { return } // get content via http client and authenticate content using hash content, err := http.GetAuthContent(uri, hash) if err != nil { return } // get abi, userdoc var obj2 map[string]json.RawMessage err = json.Unmarshal(content, &obj2) if err != nil { return } abi := []byte(obj2["abi"]) userdoc := []byte(obj2["userdoc"]) self, err = NewWithDocs(abi, userdoc, tx) return }
func TestRlpxFrameFake(t *testing.T) { buf := new(bytes.Buffer) hash := fakeHash([]byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) rw := newRlpxFrameRW(buf, secrets{ AES: crypto.Sha3(), MAC: crypto.Sha3(), IngressMAC: hash, EgressMAC: hash, }) golden := unhex(` 00828ddae471818bb0bfa6b551d1cb42 01010101010101010101010101010101 ba628a4ba590cb43f7848f41c4382885 01010101010101010101010101010101 `) // Check WriteMsg. This puts a message into the buffer. if err := Send(rw, 8, []uint{1, 2, 3, 4}); err != nil { t.Fatalf("WriteMsg error: %v", err) } written := buf.Bytes() if !bytes.Equal(written, golden) { t.Fatalf("output mismatch:\n got: %x\n want: %x", written, golden) } // Check ReadMsg. It reads the message encoded by WriteMsg, which // is equivalent to the golden message above. msg, err := rw.ReadMsg() if err != nil { t.Fatalf("ReadMsg error: %v", err) } if msg.Size != 5 { t.Errorf("msg size mismatch: got %d, want %d", msg.Size, 5) } if msg.Code != 8 { t.Errorf("msg code mismatch: got %d, want %d", msg.Code, 8) } payload, _ := ioutil.ReadAll(msg.Payload) wantPayload := unhex("C401020304") if !bytes.Equal(payload, wantPayload) { t.Errorf("msg payload mismatch:\ngot %x\nwant %x", payload, wantPayload) } }
func decodeAuthMsg(prv *ecdsa.PrivateKey, token []byte, auth []byte) (*encHandshake, error) { var err error h := new(encHandshake) // generate random keypair for session h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil) if err != nil { return nil, err } // generate random nonce h.respNonce = make([]byte, shaLen) if _, err = rand.Read(h.respNonce); err != nil { return nil, err } msg, err := crypto.Decrypt(prv, auth) if err != nil { return nil, fmt.Errorf("could not decrypt auth message (%v)", err) } // decode message parameters // signature || sha3(ecdhe-random-pubk) || pubk || nonce || token-flag h.initNonce = msg[authMsgLen-shaLen-1 : authMsgLen-1] copy(h.remoteID[:], msg[sigLen+shaLen:sigLen+shaLen+pubLen]) rpub, err := h.remoteID.Pubkey() if err != nil { return nil, fmt.Errorf("bad remoteID: %#v", err) } h.remotePub = ecies.ImportECDSAPublic(rpub) // recover remote random pubkey from signed message. if token == nil { // TODO: it is an error if the initiator has a token and we don't. check that. // no session token means we need to generate shared secret. // ecies shared secret is used as initial session token for new peers. // generate shared key from prv and remote pubkey. if token, err = h.ecdhShared(prv); err != nil { return nil, err } } signedMsg := xor(token, h.initNonce) remoteRandomPub, err := secp256k1.RecoverPubkey(signedMsg, msg[:sigLen]) if err != nil { return nil, err } // validate the sha3 of recovered pubkey remoteRandomPubMAC := msg[sigLen : sigLen+shaLen] shaRemoteRandomPub := crypto.Sha3(remoteRandomPub[1:]) if !bytes.Equal(remoteRandomPubMAC, shaRemoteRandomPub) { return nil, fmt.Errorf("sha3 of recovered ephemeral pubkey does not match checksum in auth message") } h.remoteRandomPub, _ = importPublicKey(remoteRandomPub) return h, nil }
// DeliverNodeData injects a node state data retrieval response into the queue. func (q *queue) DeliverNodeData(id string, data [][]byte, callback func(error, int)) error { q.lock.Lock() defer q.lock.Unlock() // Short circuit if the data was never requested request := q.statePendPool[id] if request == nil { return errNoFetchesPending } stateReqTimer.UpdateSince(request.Time) delete(q.statePendPool, id) // If no data was retrieved, mark their hashes as unavailable for the origin peer if len(data) == 0 { for hash, _ := range request.Hashes { request.Peer.ignored.Add(hash) } } // Iterate over the downloaded data and verify each of them errs := make([]error, 0) process := []trie.SyncResult{} for _, blob := range data { // Skip any blocks that were not requested hash := common.BytesToHash(crypto.Sha3(blob)) if _, ok := request.Hashes[hash]; !ok { errs = append(errs, fmt.Errorf("non-requested state data %x", hash)) continue } // Inject the next state trie item into the processing queue process = append(process, trie.SyncResult{hash, blob}) delete(request.Hashes, hash) delete(q.stateTaskPool, hash) } // Start the asynchronous node state data injection atomic.AddInt32(&q.stateProcessors, 1) go func() { defer atomic.AddInt32(&q.stateProcessors, -1) q.deliverNodeData(process, callback) }() // Return all failed or missing fetches to the queue for hash, index := range request.Hashes { q.stateTaskQueue.Push(hash, float32(index)) } // If none of the data items were good, it's a stale delivery switch { case len(errs) == 0: return nil case len(errs) == len(request.Hashes): return errStaleDelivery default: return fmt.Errorf("multiple failures: %v", errs) } }
func (self *Transaction) From() (common.Address, error) { pubkey, err := self.PublicKey() if err != nil { return common.Address{}, err } var addr common.Address copy(addr[:], crypto.Sha3(pubkey[1:])[12:]) return addr, nil }
func (self *Transaction) From() (common.Address, error) { pubkey := self.PublicKey() if len(pubkey) == 0 || pubkey[0] != 4 { return common.Address{}, errors.New("invalid public key") } var addr common.Address copy(addr[:], crypto.Sha3(pubkey[1:])[12:]) return addr, nil }
func (self *Trie) store(node Node) interface{} { data := common.Encode(node) if len(data) >= 32 { key := crypto.Sha3(data) self.cache.Put(key, data) return key } return node.RlpData() }
func (self *Trie) Hash() []byte { var hash []byte if self.root != nil { t := self.root.Hash() if byts, ok := t.([]byte); ok && len(byts) > 0 { hash = byts } else { hash = crypto.Sha3(common.Encode(self.root.RlpData())) } } else { hash = crypto.Sha3(common.Encode("")) } if !bytes.Equal(hash, self.roothash) { self.revisions.PushBack(self.roothash) self.roothash = hash } return hash }
func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) ([]byte, error) { b := new(bytes.Buffer) b.Write(headSpace) b.WriteByte(ptype) if err := rlp.Encode(b, req); err != nil { glog.V(logger.Error).Infoln("error encoding packet:", err) return nil, err } packet := b.Bytes() sig, err := crypto.Sign(crypto.Sha3(packet[headSize:]), priv) if err != nil { glog.V(logger.Error).Infoln("could not sign packet:", err) return nil, err } copy(packet[macSize:], sig) // add the hash to the front. Note: this doesn't protect the // packet in any way. Our public key will be part of this hash in // The future. copy(packet, crypto.Sha3(packet[macSize:])) return packet, nil }
func bloom9(b []byte) *big.Int { b = crypto.Sha3(b[:]) r := new(big.Int) for i := 0; i < 6; i += 2 { t := big.NewInt(1) b := (uint(b[i+1]) + (uint(b[i]) << 8)) & 2047 r.Or(r, t.Lsh(t, b)) } return r }
func (tx *Transaction) From() (common.Address, error) { if from := tx.from.Load(); from != nil { return from.(common.Address), nil } pubkey, err := tx.publicKey() if err != nil { return common.Address{}, err } var addr common.Address copy(addr[:], crypto.Sha3(pubkey[1:])[12:]) tx.from.Store(addr) return addr, nil }
func (self *NatSpec) makeAbi2method(abiKey [8]byte) (meth *method) { for signature, m := range self.userDoc.Methods { name := strings.Split(signature, "(")[0] hash := []byte(common.Bytes2Hex(crypto.Sha3([]byte(signature)))) var key [8]byte copy(key[:], hash[:8]) if bytes.Equal(key[:], abiKey[:]) { meth = m meth.name = name return } } return }
func TestSecureGetKey(t *testing.T) { trie := newEmptySecure() trie.Update([]byte("foo"), []byte("bar")) key := []byte("foo") value := []byte("bar") seckey := crypto.Sha3(key) if !bytes.Equal(trie.Get(key), value) { t.Errorf("Get did not return bar") } if k := trie.GetKey(seckey); !bytes.Equal(k, key) { t.Errorf("GetKey returned %q, want %q", k, key) } }
func (self *Trie) store(node Node) interface{} { data := common.Encode(node) if len(data) >= 32 { key := crypto.Sha3(data) if node.Dirty() { //fmt.Println("save", node) //fmt.Println() self.cache.Put(key, data) } return key } return node.RlpData() }