Exemple #1
1
func benchmarkAEAD(b *testing.B, c cipher.AEAD) {
	b.SetBytes(benchSize)
	input := make([]byte, benchSize)
	output := make([]byte, benchSize)
	nonce := make([]byte, c.NonceSize())
	counter := 0
	t := time.Now()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		c.Seal(output[:0], nonce, input, nil)
		counter += len(output)
	}
	ts := time.Since(t)
	b.Logf("aes-gcm speed: %.2f Mbit/s", float64(counter)*8/ts.Seconds()/1024/1024)
}
Exemple #2
0
func (alg *AesGcm) Decrypt(aad, cek, iv, cipherText, authTag []byte) (plainText []byte, err error) {

	cekSizeBits := len(cek) << 3

	if cekSizeBits != alg.keySizeBits {
		return nil, errors.New(fmt.Sprintf("AesGcm.Decrypt(): expected key of size %v bits, but was given %v bits.", alg.keySizeBits, cekSizeBits))
	}

	var block cipher.Block

	if block, err = aes.NewCipher(cek); err != nil {
		return nil, err
	}

	var aesgcm cipher.AEAD

	if aesgcm, err = cipher.NewGCM(block); err != nil {
		return nil, err
	}

	cipherWithTag := append(cipherText, authTag...)

	if plainText, err = aesgcm.Open(nil, iv, cipherWithTag, aad); err != nil {
		return nil, err
	}

	return plainText, nil
}
Exemple #3
0
// Decrypts a proto using an AEAD. Unmarshals the result into dst. The result
// should only be considered written if this function returns true.
func DecryptProto(aead cipher.AEAD, msg string, additionalData []byte, dst proto.Message) bool {
	msgBytes, err := base64.RawURLEncoding.DecodeString(msg)
	if err != nil {
		glog.V(2).Infof("Tried to decrypt proto with invalid base64: %v", err)
		return false
	}

	var msgProto pb.EncryptedMessage
	err = proto.Unmarshal(msgBytes, &msgProto)
	if err != nil {
		glog.V(2).Infof("Tried to decrypt proto with invalid pb.EncryptedMessage: %v", err)
		return false
	}

	// Decrypt in-place.
	plaintext := msgProto.Ciphertext
	plaintext, err = aead.Open(plaintext[:0], msgProto.Nonce, msgProto.Ciphertext, additionalData)
	if err != nil {
		glog.V(2).Infof("Failed to decrypt data: %v", err)
		return false
	}

	err = proto.Unmarshal(plaintext, dst)
	if err != nil {
		glog.V(2).Infof("Failed to decrypt proto: %v", err)
		return false
	}

	return true
}
Exemple #4
0
func (c AesContentCipher) encrypt(cek, plaintext, aad []byte) (iv, ciphertext, tag []byte, err error) {
	var aead cipher.AEAD
	aead, err = c.AeadFetch(cek)
	if err != nil {
		if debug.Enabled {
			debug.Printf("AeadFetch failed: %s", err)
		}
		err = fmt.Errorf("failed to fetch AEAD: %s", err)
		return
	}

	// Seal may panic (argh!), so protect ourselves from that
	defer func() {
		if e := recover(); e != nil {
			switch e.(type) {
			case error:
				err = e.(error)
			case string:
				err = errors.New(e.(string))
			default:
				err = fmt.Errorf("%s", e)
			}
			return
		}
	}()

	var bs ByteSource
	if c.NonceGenerator == nil {
		bs, err = NewRandomKeyGenerate(aead.NonceSize()).KeyGenerate()
	} else {
		bs, err = c.NonceGenerator.KeyGenerate()
	}
	if err != nil {
		return
	}
	iv = bs.Bytes()

	combined := aead.Seal(nil, iv, plaintext, aad)
	tagoffset := len(combined) - c.TagSize()
	if debug.Enabled {
		debug.Printf("tagsize = %d", c.TagSize())
	}
	tag = combined[tagoffset:]
	ciphertext = make([]byte, tagoffset)
	copy(ciphertext, combined[:tagoffset])

	if debug.Enabled {
		debug.Printf("encrypt: combined   = %x (%d)\n", combined, len(combined))
		debug.Printf("encrypt: ciphertext = %x (%d)\n", ciphertext, len(ciphertext))
		debug.Printf("encrypt: tag        = %x (%d)\n", tag, len(tag))
		debug.Printf("finally ciphertext = %x\n", ciphertext)
	}
	return
}
Exemple #5
0
func (alg *AesGcmKW) Unwrap(encryptedCek []byte, key interface{}, cekSizeBits int, header map[string]interface{}) (cek []byte, err error) {
	if kek, ok := key.([]byte); ok {

		kekSizeBits := len(kek) << 3

		if kekSizeBits != alg.keySizeBits {
			return nil, errors.New(fmt.Sprintf("AesGcmKW.Unwrap(): expected key of size %v bits, but was given %v bits.", alg.keySizeBits, kekSizeBits))
		}

		var iv, tag string

		if iv, ok = header["iv"].(string); !ok {
			return nil, errors.New("AesGcmKW.Unwrap(): expected 'iv' param in JWT header, but was not found.")
		}

		if tag, ok = header["tag"].(string); !ok {
			return nil, errors.New("AesGcmKW.Unwrap(): expected 'tag' param in JWT header, but was not found.")
		}

		var ivBytes, tagBytes []byte

		if ivBytes, err = base64url.Decode(iv); err != nil {
			return nil, err
		}

		if tagBytes, err = base64url.Decode(tag); err != nil {
			return nil, err
		}

		var block cipher.Block

		if block, err = aes.NewCipher(kek); err != nil {
			return nil, err
		}

		var aesgcm cipher.AEAD

		if aesgcm, err = cipher.NewGCM(block); err != nil {
			return nil, err
		}

		cipherAndTag := append(encryptedCek, tagBytes...)

		if cek, err = aesgcm.Open(nil, ivBytes, cipherAndTag, nil); err != nil {
			fmt.Printf("err = %v\n", err)
			return nil, err
		}

		return cek, nil
	}

	return nil, errors.New("AesGcmKW.Unwrap(): expected key to be '[]byte' array")
}
Exemple #6
0
// Encrypt a proto using an AEAD.
func EncryptProto(aead cipher.AEAD, msg proto.Message, additionalData []byte) string {
	plaintext := MarshalProtoOrPanic(msg)

	nonce := getNonce(aead.NonceSize())

	// Encrypt in-place.
	ciphertext := plaintext
	ciphertext = aead.Seal(ciphertext[:0], nonce, plaintext, additionalData)

	outBytes := MarshalProtoOrPanic(&pb.EncryptedMessage{
		Nonce:      nonce,
		Ciphertext: ciphertext,
	})

	// Return base64'd, so that the output is ASCII-safe.
	return base64.RawURLEncoding.EncodeToString(outBytes)
}
Exemple #7
0
func (alg *AesGcm) Encrypt(aad, plainText, cek []byte) (iv, cipherText, authTag []byte, err error) {

	cekSizeBits := len(cek) << 3

	if cekSizeBits != alg.keySizeBits {
		return nil, nil, nil, errors.New(fmt.Sprintf("AesGcm.Encrypt(): expected key of size %v bits, but was given %v bits.", alg.keySizeBits, cekSizeBits))
	}

	if iv, err = arrays.Random(12); err != nil {
		return nil, nil, nil, err
	}

	var block cipher.Block

	if block, err = aes.NewCipher(cek); err != nil {
		return nil, nil, nil, err
	}

	var aesgcm cipher.AEAD

	if aesgcm, err = cipher.NewGCM(block); err != nil {
		return nil, nil, nil, err
	}

	cipherWithTag := aesgcm.Seal(nil, iv, plainText, aad)

	cipherText = cipherWithTag[:len(cipherWithTag)-aesgcm.Overhead()]
	authTag = cipherWithTag[len(cipherWithTag)-aesgcm.Overhead():]

	return iv, cipherText, authTag, nil
}
Exemple #8
0
// encrypt is used to encrypt a value
func (b *AESGCMBarrier) encrypt(term uint32, gcm cipher.AEAD, plain []byte) []byte {
	// Allocate the output buffer with room for tern, version byte,
	// nonce, GCM tag and the plaintext
	capacity := termSize + 1 + gcm.NonceSize() + gcm.Overhead() + len(plain)
	size := termSize + 1 + gcm.NonceSize()
	out := make([]byte, size, capacity)

	// Set the key term
	binary.BigEndian.PutUint32(out[:4], term)

	// Set the version byte
	out[4] = aesgcmVersionByte

	// Generate a random nonce
	nonce := out[5 : 5+gcm.NonceSize()]
	rand.Read(nonce)

	// Seal the output
	out = gcm.Seal(out, nonce, plain, nil)
	return out
}
Exemple #9
0
// encrypt is used to encrypt a value
func (b *AESGCMBarrier) encrypt(gcm cipher.AEAD, plain []byte) []byte {
	// Allocate the output buffer with room for epoch, version byte,
	// nonce, GCM tag and the plaintext
	capacity := epochSize + 1 + gcm.NonceSize() + gcm.Overhead() + len(plain)
	size := epochSize + 1 + gcm.NonceSize()
	out := make([]byte, size, capacity)

	// Set the epoch to 1
	out[3] = keyEpoch

	// Set the version byte
	out[4] = aesgcmVersionByte

	// Generate a random nonce
	nonce := out[5 : 5+gcm.NonceSize()]
	rand.Read(nonce)

	// Seal the output
	out = gcm.Seal(out, nonce, plain, nil)
	return out
}
Exemple #10
0
func getErrData(aead cipher.AEAD, stream io.Reader) (string, ErrData) {
	// Decode encrypted error from STDIN (json base64 gob)
	var api APIErr
	err := json.NewDecoder(stream).Decode(&api)
	if err != nil {
		panic(err)
	}

	rawdata, err := base64.StdEncoding.DecodeString(api.Data)
	if err != nil {
		panic(err)
	}

	rawdatabuf := bytes.NewBuffer(rawdata)
	encdecoder := gob.NewDecoder(rawdatabuf)

	var encerr EncryptedError
	err = encdecoder.Decode(&encerr)
	if err != nil {
		panic(err)
	}

	errbytes, err := aead.Open(nil, encerr.Nonce, encerr.Ciphertext, nil)
	if err != nil {
		panic(err)
	}

	// Decode error struct from decrypted bytes
	errbuf := bytes.NewBuffer(errbytes)
	errdecoder := gob.NewDecoder(errbuf)

	var errdata ErrData
	err = errdecoder.Decode(&errdata)
	if err != nil {
		panic(err)
	}

	return api.Status, errdata
}
Exemple #11
0
// decrypt is used to decrypt a value
func (b *AESGCMBarrier) decrypt(path string, gcm cipher.AEAD, cipher []byte) ([]byte, error) {
	// Verify the term is always just one
	term := binary.BigEndian.Uint32(cipher[:4])
	if term != initialKeyTerm {
		return nil, fmt.Errorf("term mis-match")
	}

	// Capture the parts
	nonce := cipher[5 : 5+gcm.NonceSize()]
	raw := cipher[5+gcm.NonceSize():]
	out := make([]byte, 0, len(raw)-gcm.NonceSize())

	// Verify the cipher byte and attempt to open
	switch cipher[4] {
	case AESGCMVersion1:
		return gcm.Open(out, nonce, raw, nil)
	case AESGCMVersion2:
		return gcm.Open(out, nonce, raw, []byte(path))
	default:
		return nil, fmt.Errorf("version bytes mis-match")
	}
}
Exemple #12
0
/*
Encrypt generates a literal of the form <b64URLmetadata>.<b64URLciphertext>.<b64URLnonce> given an AEAD cipher, a metadata string and a data
string. Only the data is encrypted - the metadata must be appropriate to expose in the clear. Each call generates a random
nonce of the length required by the cipher.
*/
func Encrypt(aeadCipher cipher.AEAD, metadata, data string) (string, error) {

	var (
		nonce         = make([]byte, aeadCipher.NonceSize())
		ciphertext    []byte
		b64metadata   []byte
		b64ciphertext []byte
		b64nonce      []byte
		buf           bytes.Buffer
		err           error
	)

	//A nonce of the length required by the AEAD is generated
	_, err = rand.Read(nonce)
	if err != nil {
		return "", err
	}

	//Seal encrypts the data using the aeadCipher's key and the nonce and appends an authentication code for the metadata
	ciphertext = aeadCipher.Seal(ciphertext, nonce, []byte(data), []byte(metadata))

	//Base64 Encode metadata, ciphertext and nonce
	b64metadata = make([]byte, base64.URLEncoding.EncodedLen(len([]byte(metadata))))
	base64.URLEncoding.Encode(b64metadata, []byte(metadata))
	b64ciphertext = make([]byte, base64.URLEncoding.EncodedLen(len(ciphertext)))
	base64.URLEncoding.Encode(b64ciphertext, ciphertext)
	b64nonce = make([]byte, base64.URLEncoding.EncodedLen(len(nonce)))
	base64.URLEncoding.Encode(b64nonce, nonce)

	//Compose a <b64URLmetadata>.<b64URLciphertext>.<b64URLnonce> literal
	buf.Write(b64metadata)
	buf.Write([]byte("."))
	buf.Write(b64ciphertext)
	buf.Write([]byte("."))
	buf.Write(b64nonce)

	//Return the AEAD literal
	return string(buf.Bytes()), nil
}
Exemple #13
0
/*
Decrypt decrypts a literal of the form <b64URLmetadata>.<b64URLciphertext>.<b64URLnonce> given an AEAD cipher and
produces a metadata and data string.
*/
func Decrypt(aeadCipher cipher.AEAD, literal string) (string, string, error) {
	var (
		literalSubStrings []string
		metadata          []byte
		ciphertext        []byte
		nonce             []byte
		data              []byte
		err               error
	)

	//Split the literal into its base64 encoded metadata, ciphertext and nonce components
	literalSubStrings = strings.Split(literal, ".")
	if len(literalSubStrings) != 3 {
		return "", "", fmt.Errorf("Bad AEAD Literal: %v\n", literal)
	}

	//Decode the metadata, ciphertext and nonce
	metadata, err = base64.URLEncoding.DecodeString(literalSubStrings[0])
	if err != nil {
		return "", "", fmt.Errorf("Decode metadata failed: %v\n", literal)
	}
	ciphertext, err = base64.URLEncoding.DecodeString(literalSubStrings[1])
	if err != nil {
		return "", "", fmt.Errorf("Decode ciphertext failed: %v\n", literal)
	}
	nonce, err = base64.URLEncoding.DecodeString(literalSubStrings[2])
	if err != nil {
		return "", "", fmt.Errorf("Decode nonce failed: %v\n", literal)
	}

	//Open validates the integrity of the metadata using the authentication code in the ciphertext
	//and, if valid, decrypts the ciphertext
	data, err = aeadCipher.Open(data, nonce, ciphertext, metadata)
	if err != nil {
		return "", "", err
	}
	return string(metadata), string(data), nil
}
Exemple #14
0
// decrypt is used to decrypt a value
func (b *AESGCMBarrier) decrypt(gcm cipher.AEAD, cipher []byte) ([]byte, error) {
	// Verify the epoch
	if cipher[0] != 0 || cipher[1] != 0 || cipher[2] != 0 || cipher[3] != keyEpoch {
		return nil, fmt.Errorf("epoch mis-match")
	}

	// Verify the version byte
	if cipher[4] != aesgcmVersionByte {
		return nil, fmt.Errorf("version bytes mis-match")
	}

	// Capture the parts
	nonce := cipher[5 : 5+gcm.NonceSize()]
	raw := cipher[5+gcm.NonceSize():]
	out := make([]byte, 0, len(raw)-gcm.NonceSize())

	// Attempt to open
	return gcm.Open(out, nonce, raw, nil)
}
Exemple #15
0
// decrypt is used to decrypt a value
func (b *AESGCMBarrier) decrypt(gcm cipher.AEAD, cipher []byte) ([]byte, error) {
	// Verify the term is always just one
	term := binary.BigEndian.Uint32(cipher[:4])
	if term != initialKeyTerm {
		return nil, fmt.Errorf("term mis-match")
	}

	// Verify the version byte
	if cipher[4] != aesgcmVersionByte {
		return nil, fmt.Errorf("version bytes mis-match")
	}

	// Capture the parts
	nonce := cipher[5 : 5+gcm.NonceSize()]
	raw := cipher[5+gcm.NonceSize():]
	out := make([]byte, 0, len(raw)-gcm.NonceSize())

	// Attempt to open
	return gcm.Open(out, nonce, raw, nil)
}
Exemple #16
0
func (alg *AesGcmKW) WrapNewKey(cekSizeBits int, key interface{}, header map[string]interface{}) (cek []byte, encryptedCek []byte, err error) {
	if kek, ok := key.([]byte); ok {

		kekSizeBits := len(kek) << 3

		if kekSizeBits != alg.keySizeBits {
			return nil, nil, errors.New(fmt.Sprintf("AesGcmKW.WrapNewKey(): expected key of size %v bits, but was given %v bits.", alg.keySizeBits, kekSizeBits))
		}

		if cek, err = arrays.Random(cekSizeBits >> 3); err != nil {
			return nil, nil, err
		}

		var iv []byte

		if iv, err = arrays.Random(12); err != nil {
			return nil, nil, err
		}

		var block cipher.Block

		if block, err = aes.NewCipher(kek); err != nil {
			return nil, nil, err
		}

		var aesgcm cipher.AEAD

		if aesgcm, err = cipher.NewGCM(block); err != nil {
			return nil, nil, err
		}

		cipherWithTag := aesgcm.Seal(nil, iv, cek, nil)

		cipherText := cipherWithTag[:len(cipherWithTag)-aesgcm.Overhead()]
		authTag := cipherWithTag[len(cipherWithTag)-aesgcm.Overhead():]

		header["iv"] = base64url.Encode(iv)
		header["tag"] = base64url.Encode(authTag)

		return cek, cipherText, nil
	}

	return nil, nil, errors.New("AesGcmKW.WrapNewKey(): expected key to be '[]byte' array")
}
Exemple #17
0
func fixNonce(gcm cipher.AEAD, nonce []byte) []byte {
	realNonce := make([]byte, gcm.NonceSize())
	copy(realNonce, nonce)
	return realNonce
}
Exemple #18
0
// encrypt is used to encrypt a value
func (b *AESGCMBarrier) encrypt(path string, term uint32, gcm cipher.AEAD, plain []byte) []byte {
	// Allocate the output buffer with room for tern, version byte,
	// nonce, GCM tag and the plaintext
	capacity := termSize + 1 + gcm.NonceSize() + gcm.Overhead() + len(plain)
	size := termSize + 1 + gcm.NonceSize()
	out := make([]byte, size, capacity)

	// Set the key term
	binary.BigEndian.PutUint32(out[:4], term)

	// Set the version byte
	out[4] = b.currentAESGCMVersionByte

	// Generate a random nonce
	nonce := out[5 : 5+gcm.NonceSize()]
	rand.Read(nonce)

	// Seal the output
	switch b.currentAESGCMVersionByte {
	case AESGCMVersion1:
		out = gcm.Seal(out, nonce, plain, nil)
	case AESGCMVersion2:
		out = gcm.Seal(out, nonce, plain, []byte(path))
	default:
		panic("Unknown AESGCM version")
	}

	return out
}