Пример #1
0
// expandKey uses HKDF on SHA256 to create 256 bit random keys
// from cryptographically secure masterkey and salt.
func expandKey(masterkey []byte, nonsecretsalt []byte, count int) (keys [][]byte, err error) {

	hkdf := hkdf.New(sha256.New, masterkey, nonsecretsalt, []byte("Why not mix it up?"))

	// Generate keys
	keys = make([][]byte, count)
	for i := 0; i < count; i++ {
		keys[i] = make([]byte, 32)
		n, err := io.ReadFull(hkdf, keys[i])
		if err == nil && n != 32 {
			err = fmt.Errorf("expandKey: HKDF did not return 32 byte key. Len: %d\n", len(keys[i]))
		}
		if err != nil {
			return nil, err
		}
	}

	// Check for obvious leakage or non-randomness
	for i := 0; i < count; i++ {
		if bytes.Contains(keys[i], masterkey) {
			err = fmt.Errorf("expandKey: HKDF failed")
			return nil, err
		}
		for j := 0; j < i; j++ {
			if bytes.Equal(keys[i], keys[j]) {
				err = fmt.Errorf("expandKey: HKDF failed")
				return nil, err
			}
		}
	}

	return keys, nil
}
Пример #2
0
// Initializes a stream into an encrypted tunnel link.
func (c *Connection) initClientTunnel(strm *stream.Stream, remote uint64, id uint64, key []byte, deadline time.Time) (*link.Link, error) {
	// Set a socket deadline for finishing the handshake
	strm.Sock().SetDeadline(deadline)
	defer strm.Sock().SetDeadline(time.Time{})

	// Send the unencrypted tunnel id to associate with the remote tunnel
	init := &initPacket{ConnId: remote, TunId: id}
	if err := strm.Send(init); err != nil {
		return nil, err
	}
	// Create the encrypted link and authorize it
	hasher := func() hash.Hash { return config.HkdfHash.New() }
	hkdf := hkdf.New(hasher, key, config.HkdfSalt, config.HkdfInfo)
	conn := link.New(strm, hkdf, false)

	// Send and retrieve an authorization to verify both directions
	auth := &proto.Message{
		Head: proto.Header{
			Meta: &authPacket{Id: id},
		},
	}
	if err := conn.SendDirect(auth); err != nil {
		return nil, err
	}
	if msg, err := conn.RecvDirect(); err != nil {
		return nil, err
	} else if auth, ok := msg.Head.Meta.(*authPacket); !ok || auth.Id != id {
		return nil, errors.New("protocol violation")
	}
	conn.Start(config.IrisTunnelBuffer)

	// Return the initialized link
	return conn, nil
}
Пример #3
0
// Extracts a usable sized symmetric key and IV for the stream cipher from the huge master key, and
// creates a CTR stream cipher.
func (s *Session) makeCipher() (cipher.Stream, error) {
	// Create the key derivation function
	hasher := func() hash.Hash { return s.hash.New() }
	hkdf := hkdf.New(hasher, s.secret.Bytes(), hkdfSalt, hkdfInfo)

	// Extract the symmetric key
	key := make([]byte, s.keybits/8)
	n, err := io.ReadFull(hkdf, key)
	if n != len(key) || err != nil {
		return nil, err
	}
	// Create the block cipher
	block, err := s.crypter(key)
	if err != nil {
		return nil, err
	}
	// Extract the IV for the counter mode
	iv := make([]byte, block.BlockSize())
	n, err = io.ReadFull(hkdf, iv)
	if n != len(iv) || err != nil {
		return nil, err
	}
	// Create the stream cipher
	return cipher.NewCTR(block, iv), nil
}
Пример #4
0
// split is the final wrap-up act to be executed at the end of a succesful
// three act handshake. This function creates to internal cipherState
// instances: one which is used to encrypt messages from the initiator to the
// responder, and another which is used to encrypt message for the opposite
// direction.
func (b *BrontideMachine) split() {
	var (
		empty   []byte
		sendKey [32]byte
		recvKey [32]byte
	)

	h := hkdf.New(sha256.New, b.chainingKey[:], empty, empty)

	// If we're the initiator the the frist 32 bytes are used to encrypt
	// our messages and the second 32-bytes to decrypt their messages. For
	// the responder the opposite is true.
	if b.initiator {
		h.Read(sendKey[:])
		b.sendCipher = cipherState{}
		b.sendCipher.InitializeKey(sendKey)

		h.Read(recvKey[:])
		b.recvCipher = cipherState{}
		b.recvCipher.InitializeKey(recvKey)
	} else {
		h.Read(recvKey[:])
		b.recvCipher = cipherState{}
		b.recvCipher.InitializeKey(recvKey)

		h.Read(sendKey[:])
		b.sendCipher = cipherState{}
		b.sendCipher.InitializeKey(sendKey)
	}
}
Пример #5
0
// Derive uses HKDF with HMAC-SHA256 to derive key bytes in its material
// parameter.
func (d *Deriver) Derive(salt, context, material []byte) error {
	f := hkdf.New(sha256.New, d.secret, salt, context)
	if _, err := f.Read(material); err != nil {
		return err
	}

	return nil
}
Пример #6
0
func eciesEncrypt(rand io.Reader, pub *ecdsa.PublicKey, s1, s2 []byte, plain []byte) ([]byte, error) {
	params := pub.Curve

	// Select an ephemeral elliptic curve key pair associated with
	// elliptic curve domain parameters params
	priv, Rx, Ry, err := elliptic.GenerateKey(pub.Curve, rand)
	//fmt.Printf("Rx %s\n", utils.EncodeBase64(Rx.Bytes()))
	//fmt.Printf("Ry %s\n", utils.EncodeBase64(Ry.Bytes()))

	// Convert R=(Rx,Ry) to an octed string R bar
	// This is uncompressed
	Rb := elliptic.Marshal(pub.Curve, Rx, Ry)

	// Derive a shared secret field element z from the ephemeral secret key k
	// and convert z to an octet string Z
	z, _ := params.ScalarMult(pub.X, pub.Y, priv)
	Z := z.Bytes()
	//fmt.Printf("Z %s\n", utils.EncodeBase64(Z))

	// generate keying data K of length ecnKeyLen + macKeyLen octects from Z
	// ans s1
	kE := make([]byte, 32)
	kM := make([]byte, 32)
	hkdf := hkdf.New(primitives.GetDefaultHash(), Z, s1, nil)
	_, err = hkdf.Read(kE)
	if err != nil {
		return nil, err
	}
	_, err = hkdf.Read(kM)
	if err != nil {
		return nil, err
	}

	// Use the encryption operation of the symmetric encryption scheme
	// to encrypt m under EK as ciphertext EM
	EM, err := aesEncrypt(kE, plain)

	// Use the tagging operation of the MAC scheme to compute
	// the tag D on EM || s2
	mac := hmac.New(primitives.GetDefaultHash(), kM)
	mac.Write(EM)
	if len(s2) > 0 {
		mac.Write(s2)
	}
	D := mac.Sum(nil)

	// Output R,EM,D
	ciphertext := make([]byte, len(Rb)+len(EM)+len(D))
	//fmt.Printf("Rb %s\n", utils.EncodeBase64(Rb))
	//fmt.Printf("EM %s\n", utils.EncodeBase64(EM))
	//fmt.Printf("D %s\n", utils.EncodeBase64(D))
	copy(ciphertext, Rb)
	copy(ciphertext[len(Rb):], EM)
	copy(ciphertext[len(Rb)+len(EM):], D)

	return ciphertext, nil
}
Пример #7
0
func calculateSignatureSecret(secret []byte) ([]byte, error) {
	signatureSecretHkdf := hkdf.New(sha256.New, []byte(secret), nil, []byte(HKDF_INFO_SIGNING))

	signatureSecret := make([]byte, sha256.Size)
	if _, err := io.ReadFull(signatureSecretHkdf, signatureSecret); err != nil {
		return nil, err
	}

	return signatureSecret, nil
}
Пример #8
0
// Creates a new, double link session for authenticated data transfer. The
// initiator is used to decide the key derivation order for the channels.
func newSession(conn *stream.Stream, secret []byte, server bool) *Session {
	// Create the key derivation function
	hasher := func() hash.Hash { return config.HkdfHash.New() }
	hkdf := hkdf.New(hasher, secret, config.HkdfSalt, config.HkdfInfo)

	// Create the encrypted control link
	return &Session{
		kdf:      hkdf,
		CtrlLink: link.New(conn, hkdf, server),
	}
}
Пример #9
0
// Initializes a stream into an encrypted tunnel link.
func (o *Overlay) initServerTunnel(strm *stream.Stream) error {
	// Set a socket deadline for finishing the handshake
	strm.Sock().SetDeadline(time.Now().Add(config.IrisTunnelInitTimeout))
	defer strm.Sock().SetDeadline(time.Time{})

	// Fetch the unencrypted client initiator
	init := new(initPacket)
	if err := strm.Recv(init); err != nil {
		return err
	}
	o.lock.RLock()
	c, ok := o.conns[init.ConnId]
	o.lock.RUnlock()
	if !ok {
		return errors.New("connection not found")
	}
	c.tunLock.RLock()
	tun, ok := c.tunLive[init.TunId]
	c.tunLock.RUnlock()
	if !ok {
		return errors.New("tunnel not found")
	}
	// Create the encrypted link
	hasher := func() hash.Hash { return config.HkdfHash.New() }
	hkdf := hkdf.New(hasher, tun.secret, config.HkdfSalt, config.HkdfInfo)
	conn := link.New(strm, hkdf, true)

	// Send and retrieve an authorization to verify both directions
	auth := &proto.Message{
		Head: proto.Header{
			Meta: &authPacket{Id: tun.id},
		},
	}
	if err := conn.SendDirect(auth); err != nil {
		return err
	}
	if msg, err := conn.RecvDirect(); err != nil {
		return err
	} else if auth, ok := msg.Head.Meta.(*authPacket); !ok || auth.Id != tun.id {
		return errors.New("protocol violation")
	}
	conn.Start(config.IrisTunnelBuffer)

	// Send back the initialized link to the pending tunnel
	select {
	case tun.initDone <- conn:
		// Connection handled by initiator
		return nil
	case <-tun.initStop:
		// Initiator timed out or terminated, close
		conn.Close()
		return nil // No error, since tunnel was handled, albeit not as expected
	}
}
Пример #10
0
func generateDerivedSecret(secret []byte, salt string, encodedTokenSecret string) (string, error) {
	derivedHkdf := hkdf.New(sha256.New, []byte(secret), []byte(salt), []byte(HKDF_INFO_DERIVE+encodedTokenSecret))

	derivedSecret := make([]byte, sha256.Size)
	_, err := io.ReadFull(derivedHkdf, derivedSecret)
	if err != nil {
		return "", err
	}

	return base64.URLEncoding.EncodeToString(derivedSecret), nil
}
Пример #11
0
// Kdf extracts and expands KEY_SEED via HKDF-SHA256 and returns `okm_len` bytes
// of key material.
func Kdf(keySeed []byte, okmLen int) []byte {
	kdf := hkdf.New(sha256.New, keySeed, tKey, mExpand)
	okm := make([]byte, okmLen)
	n, err := io.ReadFull(kdf, okm)
	if err != nil {
		panic(fmt.Sprintf("BUG: Failed HKDF: %s", err.Error()))
	} else if n != len(okm) {
		panic(fmt.Sprintf("BUG: Got truncated HKDF output: %d", n))
	}

	return okm
}
Пример #12
0
// Sha512 returns a 256-bit key
func Sha512(master, salt, info []byte) ([32]byte, error) {
	hash := sha512.New
	hkdf := hkdf.New(hash, master, salt, info)

	key := make([]byte, 32) // 256 bit
	_, err := io.ReadFull(hkdf, key)

	var result [32]byte
	copy(result[:], key)

	return result, err
}
Пример #13
0
// DeriveSecrets derives the requested number of bytes using HKDF, given
// the inputKeyMaterial, salt and the info
func DeriveSecrets(inputKeyMaterial, salt, info []byte, size int) ([]byte, error) {
	hkdf := hkdf.New(sha256.New, inputKeyMaterial, salt, info)

	secrets := make([]byte, size)
	n, err := io.ReadFull(hkdf, secrets)
	if err != nil {
		return nil, err
	}
	if n != size {
		return nil, err
	}
	return secrets, nil
}
Пример #14
0
// XXX TODO: return err if init() or Reset() has not been called
func (skgen *SecretKeyGen) Read(p []byte) (n int, err error) {
	prng := make([]byte, 256)
	n, err = io.ReadFull(rand.Reader, prng)
	if err != nil {
		//fmt.Fprintf(os.Stderr, "POUET POUET PROUT Error")
		//fmt.Println(err)
		return n, err
	}

	my_hkdf := hkdf.New(skgen.hash, skgen.input_pbkdf, prng, skgen.info_hkdf)
	n, err = io.ReadFull(my_hkdf, p)
	return n, err
}
Пример #15
0
// DeriveKey is used to derive the encryption key that should be used depending
// on the policy. If derivation is disabled the raw key is used and no context
// is required, otherwise the KDF mode is used with the context to derive the
// proper key.
func (p *policy) DeriveKey(context []byte, ver int) ([]byte, error) {
	if !p.Type.DerivationSupported() {
		return nil, errutil.UserError{Err: fmt.Sprintf("derivation not supported for key type %v", p.Type)}
	}

	if p.Keys == nil || p.LatestVersion == 0 {
		return nil, errutil.InternalError{Err: "unable to access the key; no key versions found"}
	}

	if ver <= 0 || ver > p.LatestVersion {
		return nil, errutil.UserError{Err: "invalid key version"}
	}

	// Fast-path non-derived keys
	if !p.Derived {
		return p.Keys[ver].AESKey, nil
	}

	// Ensure a context is provided
	if len(context) == 0 {
		return nil, errutil.UserError{Err: "missing 'context' for key deriviation. The key was created using a derived key, which means additional, per-request information must be included in order to encrypt or decrypt information"}
	}

	switch p.KDF {
	case kdf_hmac_sha256_counter:
		prf := kdf.HMACSHA256PRF
		prfLen := kdf.HMACSHA256PRFLen
		return kdf.CounterMode(prf, prfLen, p.Keys[ver].AESKey, context, 256)
	case kdf_hkdf_sha256:
		reader := hkdf.New(sha256.New, p.Keys[ver].AESKey, nil, context)
		derBytes := bytes.NewBuffer(nil)
		derBytes.Grow(32)
		limReader := &io.LimitedReader{
			R: reader,
			N: 32,
		}
		n, err := derBytes.ReadFrom(limReader)
		if err != nil {
			return nil, errutil.InternalError{Err: fmt.Sprintf("error reading returned derived bytes: %v", err)}
		}
		if n != 32 {
			return nil, errutil.InternalError{Err: fmt.Sprintf("unable to read enough derived bytes, needed 32, got %d", n)}
		}
		return derBytes.Bytes(), nil
	default:
		return nil, errutil.InternalError{Err: "unsupported key derivation mode"}
	}
}
Пример #16
0
// First argument is the algorithm used. "plain" (AlgoPlain) and
// "dh-ietf1024-sha256-aes128-cbc-pkcs7" (AlgoDH) are supported.
//
// The dbus api has the caller supply their DH public key and returns
// the other side's public key, but this implementation generates a
// new keypair, does the exchange, derives the encryption key, and then
// stores it in the returned Session.
func (s Service) OpenSession(algo string, args ...interface{}) (Session, error) {
	// spec: OpenSession(IN String algorithm, IN Variant input, OUT Variant output, OUT ObjectPath result);
	var ret Session
	conn, err := dbus.SessionBus()
	if err != nil {
		return ret, err
	}
	switch algo {
	case AlgoPlain:
		var discard dbus.Variant
		var sessionPath dbus.ObjectPath
		err = s.Call(_ServiceOpenSession, 0, algo, dbus.MakeVariant("")).Store(&discard, &sessionPath)
		if err != nil {
			return ret, err
		}
		ret = Session{conn.Object(ServiceName, sessionPath), algo, nil}
	case AlgoDH:
		// see http://standards.freedesktop.org/secret-service/ch07s03.html
		var sessionPath dbus.ObjectPath
		var srvReply dbus.Variant
		var srvPub []byte
		symKey := make([]byte, aes.BlockSize)
		grp, err := dhkx.GetGroup(2)
		if err != nil {
			return ret, err
		}
		privKey, err := grp.GeneratePrivateKey(rand.Reader)
		if err != nil {
			return ret, err
		}
		err = s.Call(_ServiceOpenSession, 0, algo, dbus.MakeVariant(privKey.Bytes())).Store(&srvReply, &sessionPath)
		if err != nil {
			return ret, err
		}
		srvPub = srvReply.Value().([]byte)
		sharedKey, err := grp.ComputeKey(dhkx.NewPublicKey(srvPub), privKey)
		if err != nil {
			return ret, err
		}
		_, err = io.ReadFull(hkdf.New(sha256.New, sharedKey.Bytes(), nil, nil), symKey)
		ret = Session{conn.Object(ServiceName, sessionPath), algo, symKey}
	default:
		err = InvalidAlgorithm
	}
	return ret, err
}
Пример #17
0
// mixKey is implements a basic HKDF-based key rachet. This method is called
// with the result of each DH output generated during the handshake process.
// The first 32 bytes extract from the HKDF reader is the next chaining key,
// then latter 32 bytes become the temp secret key using within any future AEAD
// operations until another DH operation is performed.
func (s *symmetricState) mixKey(input []byte) {
	var info []byte

	secret := input
	salt := s.chainingKey
	h := hkdf.New(sha256.New, secret, salt[:], info)

	// hkdf(input, ck, zero)
	// |
	// | \
	// |  \
	// ck  k
	h.Read(s.chainingKey[:])
	h.Read(s.tempKey[:])

	// cipher.k = temp_key
	s.InitializeKey(s.tempKey)
}
Пример #18
0
// deriveElkremRoot derives an elkrem root unique to a channel given the
// private key for our public key in the 2-of-2 multi-sig, and the remote
// node's multi-sig public key. The root is derived using the HKDF[1][2]
// instantiated with sha-256. The secret data used is our multi-sig private
// key, with the salt being the remote node's public key.
//
// [1]: https://eprint.iacr.org/2010/264.pdf
// [2]: https://tools.ietf.org/html/rfc5869
func deriveElkremRoot(elkremDerivationRoot *btcec.PrivateKey,
	localMultiSigKey *btcec.PublicKey,
	remoteMultiSigKey *btcec.PublicKey) wire.ShaHash {

	secret := elkremDerivationRoot.Serialize()
	salt := localMultiSigKey.SerializeCompressed()
	info := remoteMultiSigKey.SerializeCompressed()

	rootReader := hkdf.New(sha256.New, secret, salt, info)

	// It's safe to ignore the error her as we know for sure that we won't
	// be draining the HKDF past its available entropy horizon.
	// TODO(roasbeef): revisit...
	var elkremRoot wire.ShaHash
	rootReader.Read(elkremRoot[:])

	return elkremRoot
}
Пример #19
0
// Usage example that expands one master key into three other cryptographically
// secure keys.
func Example_usage() {
	// Underlying hash function to use
	hash := sha256.New

	// Cryptographically secure master key.
	master := []byte{0x00, 0x01, 0x02, 0x03} // i.e. NOT this.

	// Non secret salt, optional (can be nil)
	// Recommended: hash-length sized random
	salt := make([]byte, hash().Size())
	n, err := io.ReadFull(rand.Reader, salt)
	if n != len(salt) || err != nil {
		fmt.Println("error:", err)
		return
	}

	// Non secret context specific info, optional (can be nil).
	// Note, independent from the master key.
	info := []byte{0x03, 0x14, 0x15, 0x92, 0x65}

	// Create the key derivation function
	hkdf := hkdf.New(hash, master, salt, info)

	// Generate the required keys
	keys := make([][]byte, 3)
	for i := 0; i < len(keys); i++ {
		keys[i] = make([]byte, 24)
		n, err := io.ReadFull(hkdf, keys[i])
		if n != len(keys[i]) || err != nil {
			fmt.Println("error:", err)
			return
		}
	}

	// Keys should contain 192 bit random keys
	for i := 1; i <= len(keys); i++ {
		fmt.Printf("Key #%d: %v\n", i, !bytes.Equal(keys[i-1], make([]byte, 24)))
	}

	// Output:
	// Key #1: true
	// Key #2: true
	// Key #3: true
}
Пример #20
0
// deriveSymmetricKeys derives the symmetric cryptoKey and hmacKey from the
// given messageKey.
func deriveSymmetricKeys(messageKey *[64]byte) (
	cryptoKey, hmacKey []byte,
	err error,
) {
	hkdf := hkdf.New(sha512.New, messageKey[:], nil, nil)

	// derive crypto key for AES-256
	cryptoKey = make([]byte, 32)
	if _, err := io.ReadFull(hkdf, cryptoKey); err != nil {
		return nil, nil, err
	}

	// derive HMAC key for SHA-512 HMAC
	hmacKey = make([]byte, 32)
	if _, err := io.ReadFull(hkdf, hmacKey); err != nil {
		return nil, nil, err
	}

	return
}
Пример #21
0
// IMPORTANT !!!
// If someone changes the hash function, then the salt needs to have the exactly same lenght!
// So be careful when touching this.
func deriveNonce(masterKey [keySize]byte, salt [keySize]byte, context string, counterValue string) ([nonceSize]byte, error) {
	var data24 [nonceSize]byte
	// Underlying hash function to use
	hash := sha256.New

	// Create the key derivation function
	hkdf := hkdf.New(hash, masterKey[:], salt[:], []byte(context+counterValue))
	// Generate the required keys
	key := make([]byte, nonceSize)
	n, err := io.ReadFull(hkdf, key)
	if n != len(key) || err != nil {
		return data24, err
	}

	total := copy(data24[:], key[:nonceSize])
	if total != nonceSize {
		return data24, errors.New("Could not derive a nonce.")
	}
	return data24, nil

}
Пример #22
0
// deriveRootKey derives the next root key from t1, t2, t3, and the
// previousRootKeyHash (if it exists).
func deriveRootKey(
	t1, t2, t3 *[32]byte,
	previousRootKeyHash *[64]byte,
) (*[32]byte, error) {
	master := make([]byte, 32+32+32+64)
	copy(master[:], t1[:])
	copy(master[32:], t2[:])
	copy(master[64:], t3[:])
	if previousRootKeyHash != nil {
		copy(master[96:], previousRootKeyHash[:])
	}

	hkdf := hkdf.New(sha512.New, master, nil, nil)

	// derive root key
	var rootKey [32]byte // we operate on 256-bit security margins
	if _, err := io.ReadFull(hkdf, rootKey[:]); err != nil {
		return nil, err
	}

	return &rootKey, nil
}
Пример #23
0
func generateToken(secret []byte, payload TokenPayload) (string, error) {
	secretHkdf := hkdf.New(sha256.New, []byte(secret), nil, []byte(HKDF_INFO_SIGNING))

	signatureSecret := make([]byte, sha256.Size)
	_, err := io.ReadFull(secretHkdf, signatureSecret)
	if err != nil {
		return "", err
	}

	encodedPayload, err := json.Marshal(payload)
	if err != nil {
		return "", err
	}

	// Calculate and encode the token secret
	mac := hmac.New(sha256.New, signatureSecret)
	mac.Write(encodedPayload)
	payloadSignature := mac.Sum(nil)

	tokenSecret := append(encodedPayload, payloadSignature...)

	return base64.URLEncoding.EncodeToString(tokenSecret), nil
}
Пример #24
0
func (kx *KeyExchange) derivePassword() error {
	serialised, err := proto.Marshal(kx.sharedSecret.toProto())
	if err != nil {
		return err
	}

	if kx.Testing || kx.sharedSecret.isStrongRandom() {
		h := hkdf.New(sha256.New, serialised, nil, []byte("PANDA strong secret expansion"))
		if _, err := h.Read(kx.key[:]); err != nil {
			return err
		}
		if _, err := h.Read(kx.meeting1[:]); err != nil {
			return err
		}
		if _, err := h.Read(kx.meeting2[:]); err != nil {
			return err
		}
	} else {
		var data []byte
		if runtime.GOARCH == "386" && runtime.GOOS == "linux" {
			// We're having GC problems on 32-bit systems with the
			// scrypt allocation. In order to help the GC out, the
			// scrypt computation is done in a subprocess.
			cmd := exec.Command("/proc/self/exe", "--panda-scrypt")
			var in, out bytes.Buffer
			binary.Write(&in, binary.LittleEndian, uint32(len(serialised)))
			in.Write(serialised)

			cmd.Stdin = &in
			cmd.Stdout = &out
			cmd.Stderr = os.Stderr
			if err := cmd.Run(); err != nil {
				return err
			}
			data = out.Bytes()
			if len(data) != 32*3 {
				return errors.New("scrypt subprocess returned wrong number of bytes: " + strconv.Itoa(len(data)))
			}
		} else {
			if data, err = scrypt.Key(serialised, nil, 1<<17, 16, 4, 32*3); err != nil {
				return err
			}
		}

		copy(kx.key[:], data)
		copy(kx.meeting1[:], data[32:])
		copy(kx.meeting2[:], data[64:])
	}

	var encryptedDHPublic [32]byte
	rijndael.NewCipher(&kx.key).Encrypt(&encryptedDHPublic, &kx.dhPublic)

	l := len(encryptedDHPublic)
	if padding := kx.meetingPlace.Padding(); l > padding {
		return errors.New("panda: initial message too large for meeting place")
	} else if l < padding {
		l = padding
	}

	kx.message1 = make([]byte, l)
	copy(kx.message1, encryptedDHPublic[:])
	if _, err := io.ReadFull(kx.rand, kx.message1[len(encryptedDHPublic):]); err != nil {
		return err
	}

	return nil
}
Пример #25
0
func TestSessions(t *testing.T) {
	tmpdir, keyDB, err := createDB()
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmpdir)
	defer keyDB.Close()
	// make sure sessions are empty initially
	sessionKey := base64.Encode(cipher.SHA512([]byte("key")))
	rootKeyHash, _, _, err := keyDB.GetSession(sessionKey)
	if err != sql.ErrNoRows {
		t.Error("should fail with sql.ErrNoRows")
	}
	if rootKeyHash != "" {
		t.Error("rootKeyHash is supposed to be empty")
	}
	// store root key hash
	rk := base64.Encode(cipher.SHA256([]byte("rootkey")))
	master := make([]byte, 96)
	if _, err := io.ReadFull(cipher.RandReader, master); err != nil {
		t.Fatal(err)
	}
	kdf := hkdf.New(sha512.New, master, nil, nil)
	chainKey := make([]byte, 32)
	if _, err := io.ReadFull(kdf, chainKey); err != nil {
		t.Fatal(err)
	}
	send, recv, err := deriveKeys(chainKey, kdf)
	if err != nil {
		t.Fatal(err)
	}
	err = keyDB.AddSession(sessionKey, rk, base64.Encode(chainKey), send, recv)
	if err != nil {
		t.Fatal(err)
	}
	// check root key hash
	rootKeyHash, _, n, err := keyDB.GetSession(sessionKey)
	if err != nil {
		t.Fatal(err)
	}
	if rootKeyHash != rk {
		t.Error("rootKeyHash is supposed to equal rk")
	}
	if n != msg.NumOfFutureKeys {
		t.Error("n is supposed to equal msg.NumOfFutureKeys")
	}
	// update root key hash
	chainKey = make([]byte, 32)
	if _, err := io.ReadFull(kdf, chainKey); err != nil {
		t.Fatal(err)
	}
	send, recv, err = deriveKeys(chainKey, kdf)
	if err != nil {
		t.Fatal(err)
	}
	err = keyDB.AddSession(sessionKey, rk, base64.Encode(chainKey), send, recv)
	if err != nil {
		t.Fatal(err)
	}
	// check updated root key hash
	rootKeyHash, _, n, err = keyDB.GetSession(sessionKey)
	if err != nil {
		t.Fatal(err)
	}
	if rootKeyHash != rk {
		t.Error("rootKeyHash is supposed to equal rk")
	}
	if n != 2*msg.NumOfFutureKeys {
		t.Error("n is supposed to equal 2*msg.NumOfFutureKeys")
	}

	// TODO: improve tests for message keys
	_, err = keyDB.GetMessageKey(sessionKey, true, 0)
	if err != nil {
		t.Fatal(err)
	}
	if err := keyDB.DelMessageKey(sessionKey, true, 0); err != nil {
		t.Fatal(err)
	}
}
Пример #26
0
func eciesDecrypt(priv *ecdsa.PrivateKey, s1, s2 []byte, ciphertext []byte) ([]byte, error) {
	params := priv.Curve

	var (
		rLen   int
		hLen   = primitives.GetDefaultHash()().Size()
		mStart int
		mEnd   int
	)

	//fmt.Printf("Decrypt\n")
	switch ciphertext[0] {
	case 2, 3:
		rLen = ((priv.PublicKey.Curve.Params().BitSize + 7) / 8) + 1
		if len(ciphertext) < (rLen + hLen + 1) {
			return nil, fmt.Errorf("Invalid ciphertext len [First byte = %d]", ciphertext[0])
		}
		break
	case 4:
		rLen = 2*((priv.PublicKey.Curve.Params().BitSize+7)/8) + 1
		if len(ciphertext) < (rLen + hLen + 1) {
			return nil, fmt.Errorf("Invalid ciphertext len [First byte = %d]", ciphertext[0])
		}
		break

	default:
		return nil, fmt.Errorf("Invalid ciphertext. Invalid first byte. [%d]", ciphertext[0])
	}

	mStart = rLen
	mEnd = len(ciphertext) - hLen
	//fmt.Printf("Rb %s\n", utils.EncodeBase64(ciphertext[:rLen]))

	Rx, Ry := elliptic.Unmarshal(priv.Curve, ciphertext[:rLen])
	if Rx == nil {
		return nil, errors.New("Invalid ephemeral PK")
	}
	if !priv.Curve.IsOnCurve(Rx, Ry) {
		return nil, errors.New("Invalid point on curve")
	}
	//fmt.Printf("Rx %s\n", utils.EncodeBase64(Rx.Bytes()))
	//fmt.Printf("Ry %s\n", utils.EncodeBase64(Ry.Bytes()))

	// Derive a shared secret field element z from the ephemeral secret key k
	// and convert z to an octet string Z
	z, _ := params.ScalarMult(Rx, Ry, priv.D.Bytes())
	Z := z.Bytes()
	//fmt.Printf("Z %s\n", utils.EncodeBase64(Z))

	// generate keying data K of length ecnKeyLen + macKeyLen octects from Z
	// ans s1
	kE := make([]byte, 32)
	kM := make([]byte, 32)
	hkdf := hkdf.New(primitives.GetDefaultHash(), Z, s1, nil)
	_, err := hkdf.Read(kE)
	if err != nil {
		return nil, err
	}
	_, err = hkdf.Read(kM)
	if err != nil {
		return nil, err
	}

	// Use the tagging operation of the MAC scheme to compute
	// the tag D on EM || s2 and then compare
	mac := hmac.New(primitives.GetDefaultHash(), kM)
	mac.Write(ciphertext[mStart:mEnd])
	if len(s2) > 0 {
		mac.Write(s2)
	}
	D := mac.Sum(nil)

	//fmt.Printf("EM %s\n", utils.EncodeBase64(ciphertext[mStart:mEnd]))
	//fmt.Printf("D' %s\n", utils.EncodeBase64(D))
	//fmt.Printf("D %s\n", utils.EncodeBase64(ciphertext[mEnd:]))
	if subtle.ConstantTimeCompare(ciphertext[mEnd:], D) != 1 {
		return nil, errors.New("Tag check failed")
	}

	// Use the decryption operation of the symmetric encryption scheme
	// to decryptr EM under EK as plaintext

	plaintext, err := aesDecrypt(kE, ciphertext[mStart:mEnd])

	return plaintext, err
}