Example #1
0
func TestHashqueryRequest(t *testing.T) {
	key := MustInputAscKey(t, "uat.asc")
	// Determine reference digest to compare with
	h := md5.New()
	refDigestStr := SksDigest(key, h)
	refDigest := h.Sum(nil)
	// Parse url for request
	url, err := url.Parse("/pks/hashquery")
	assert.Nil(t, err)
	// hashquery contents (sks recon wire protocol)
	var buf bytes.Buffer
	err = recon.WriteInt(&buf, 1)
	assert.Nil(t, err)
	err = recon.WriteInt(&buf, len(refDigest))
	assert.Nil(t, err)
	_, err = buf.Write(refDigest)
	assert.Nil(t, err)
	// Create an HTTP request
	req := &http.Request{
		Method: "POST",
		URL:    url,
		Body:   ioutil.NopCloser(bytes.NewBuffer(buf.Bytes())),
	}
	// Parse it
	hq := hkp.NewHashQuery()
	hq.Request = req
	err = hq.Parse()
	assert.Nil(t, err)
	assert.Equal(t, refDigestStr, hq.Digests[0])
	t.Log(hq.Digests)
}
Example #2
0
func (hq *HashQueryResponse) WriteTo(w http.ResponseWriter) (err error) {
	w.Header().Set("Content-Type", "pgp/keys")
	// Write the number of keys
	err = recon.WriteInt(w, len(hq.Keys))
	for _, key := range hq.Keys {
		// Write each key in binary packet format, prefixed with length
		keybuf := bytes.NewBuffer(nil)
		err = WritePackets(keybuf, key)
		if err != nil {
			return
		}
		err = recon.WriteInt(w, keybuf.Len())
		if err != nil {
			return
		}
		_, err = w.Write(keybuf.Bytes())
		if err != nil {
			return
		}
	}
	// SKS expects hashquery response to terminate with a CRLF
	_, err = w.Write([]byte{0x0d, 0x0a})
	return
}
Example #3
0
func (r *SksPeer) requestChunk(rcvr *recon.Recover, chunk []*Zp) (err error) {
	var remoteAddr string
	remoteAddr, err = rcvr.HkpAddr()
	if err != nil {
		return err
	}
	// Make an sks hashquery request
	hqBuf := bytes.NewBuffer(nil)
	err = recon.WriteInt(hqBuf, len(chunk))
	if err != nil {
		return err
	}
	for _, z := range chunk {
		zb := z.Bytes()
		zb = recon.PadSksElement(zb)
		// Hashquery elements are 16 bytes (length_of(P_SKS)-1)
		zb = zb[:len(zb)-1]
		err = recon.WriteInt(hqBuf, len(zb))
		if err != nil {
			return err
		}
		_, err = hqBuf.Write(zb)
		if err != nil {
			return err
		}
	}
	resp, err := http.Post(fmt.Sprintf("http://%s/pks/hashquery", remoteAddr),
		"sks/hashquery", bytes.NewReader(hqBuf.Bytes()))
	if err != nil {
		return err
	}
	// Store response in memory. Connection may timeout if we
	// read directly from it while loading.
	var body *bytes.Buffer
	{
		defer resp.Body.Close()
		bodyBuf, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return err
		}
		body = bytes.NewBuffer(bodyBuf)
	}
	var nkeys, keyLen int
	nkeys, err = recon.ReadInt(body)
	if err != nil {
		return err
	}
	log.Println("Response from server:", nkeys, " keys found")
	for i := 0; i < nkeys; i++ {
		keyLen, err = recon.ReadInt(body)
		if err != nil {
			return err
		}
		keyBuf := bytes.NewBuffer(nil)
		_, err = io.CopyN(keyBuf, body, int64(keyLen))
		if err != nil {
			return err
		}
		log.Println("Key#", i+1, ":", keyLen, "bytes")
		// Merge locally
		recoverKey := RecoverKey{
			Keytext:  keyBuf.Bytes(),
			Source:   rcvr.RemoteAddr.String(),
			response: make(chan hkp.Response)}
		go func() {
			r.RecoverKey <- recoverKey
		}()
		resp := <-recoverKey.response
		if resp, ok := resp.(*RecoverKeyResponse); ok {
			if resp.Error() != nil {
				log.Println("Error adding key:", resp.Error())
			}
		} else if resp != nil {
			log.Println("Error adding key:", resp.Error())
		} else {
			log.Println("Empty response from recovering key!")
		}
	}
	// Read last two bytes (CRLF, why?), or SKS will complain.
	body.Read(make([]byte, 2))
	return
}