Example #1
0
func TestCBCPKCS7Encrypt_IVIsRandom(t *testing.T) {
	// Encrypt two times with same key. The first 16 bytes should be
	// different if IV is random.
	key := make([]byte, 32)
	rand.Reader.Read(key)
	t.Log("Key 1", key)

	var msg = []byte("a message to encrypt")

	cipher1, err := primitives.CBCPKCS7Encrypt(key, msg)
	if err != nil {
		t.Fatalf("Error encrypting the message.")
	}

	// expecting a different IV if same message is encrypted with same key
	cipher2, err := primitives.CBCPKCS7Encrypt(key, msg)
	if err != nil {
		t.Fatal("Error encrypting the message.")
	}

	iv1 := cipher1[:aes.BlockSize]
	iv2 := cipher2[:aes.BlockSize]

	t.Log("Cipher 1: ", iv1)
	t.Log("Cipher 2: ", iv2)
	t.Log("bytes.Equal: ", bytes.Equal(iv1, iv2))

	if bytes.Equal(iv1, iv2) {
		t.Fatal("Error: ciphers contain identical initialisation vectors.")
	}

}
Example #2
0
// TestCBCPKCS7Encrypt_VerifyRandomIVs encrypts twice with same key. The first 16 bytes should be different if IV is generated randomly.
func TestCBCPKCS7Encrypt_VerifyRandomIVs(t *testing.T) {

	key := make([]byte, aes.BlockSize)
	rand.Reader.Read(key)
	t.Log("Key 1", key)

	var ptext = []byte("a message to encrypt")

	ciphertext1, err := primitives.CBCPKCS7Encrypt(key, ptext)
	if err != nil {
		t.Fatalf("Error encrypting '%s': %s", ptext, err)
	}

	// Expecting a different IV if same message is encrypted with same key
	ciphertext2, err := primitives.CBCPKCS7Encrypt(key, ptext)
	if err != nil {
		t.Fatalf("Error encrypting '%s': %s", ptext, err)
	}

	iv1 := ciphertext1[:aes.BlockSize]
	iv2 := ciphertext2[:aes.BlockSize]

	t.Log("Ciphertext1: ", iv1)
	t.Log("Ciphertext2: ", iv2)
	t.Log("bytes.Equal: ", bytes.Equal(iv1, iv2))

	if bytes.Equal(iv1, iv2) {
		t.Fatal("Error: ciphertexts contain identical initialization vectors (IVs)")
	}
}
Example #3
0
func TestCBCPKCS7EncryptCBCPKCS7Decrypt(t *testing.T) {
	// Encrypt with CBCPKCS7Encrypt and Decrypt with CBCPKCS7Decrypt
	// The purpose of this test is not to test the implementation of the AES standard
	// library but to verify the code wrapping/unwrapping the AES cipher.

	key := make([]byte, primitives.AESKeyLength)
	rand.Reader.Read(key)

	var msg = []byte("a message with arbitrary length (42 bytes)")

	encrypted, encErr := primitives.CBCPKCS7Encrypt(key, msg)

	if encErr != nil {
		t.Fatalf("Error encrypting message %v", encErr)
	}

	decrypted, dErr := primitives.CBCPKCS7Decrypt(key, encrypted)

	if dErr != nil {
		t.Fatalf("Error encrypting message %v", dErr)
	}

	if string(msg[:]) != string(decrypted[:]) {
		t.Fatalf("Decrypt( Encrypt(msg) ) != msg: Ciphertext decryption with the same key must restore the original message!")
	}

}
Example #4
0
// TestAESRelatedUtilFunctions tests various functions commonly used in fabric wrt AES
func TestAESRelatedUtilFunctions(t *testing.T) {

	key, err := primitives.GenAESKey()
	if err != nil {
		t.Fatalf("Failed generating AES key [%s]", err)
	}

	for i := 1; i < 100; i++ {
		len, err := rand.Int(rand.Reader, big.NewInt(1024))
		if err != nil {
			t.Fatalf("Failed generating AES key [%s]", err)
		}
		msg, err := primitives.GetRandomBytes(int(len.Int64()) + 1)
		if err != nil {
			t.Fatalf("Failed generating AES key [%s]", err)
		}

		ct, err := primitives.CBCPKCS7Encrypt(key, msg)
		if err != nil {
			t.Fatalf("Failed encrypting [%s]", err)
		}

		msg2, err := primitives.CBCPKCS7Decrypt(key, ct)
		if err != nil {
			t.Fatalf("Failed decrypting [%s]", err)
		}

		if 0 != bytes.Compare(msg, msg2) {
			t.Fatalf("Wrong decryption output [%x][%x]", msg, msg2)
		}

	}

}
Example #5
0
// TestCBCPKCS7EncryptCBCPKCS7Decrypt encrypts using CBCPKCS7Encrypt and decrypts using CBCPKCS7Decrypt.
func TestCBCPKCS7EncryptCBCPKCS7Decrypt(t *testing.T) {

	// Note: The purpose of this test is not to test AES-256 in CBC mode's strength
	// ... but rather to verify the code wrapping/unwrapping the cipher.
	key := make([]byte, primitives.AESKeyLength)
	rand.Reader.Read(key)

	//                  123456789012345678901234567890123456789012
	var ptext = []byte("a message with arbitrary length (42 bytes)")

	encrypted, encErr := primitives.CBCPKCS7Encrypt(key, ptext)
	if encErr != nil {
		t.Fatalf("Error encrypting '%s': %s", ptext, encErr)
	}

	decrypted, dErr := primitives.CBCPKCS7Decrypt(key, encrypted)
	if dErr != nil {
		t.Fatalf("Error decrypting the encrypted '%s': %v", ptext, dErr)
	}

	if string(ptext[:]) != string(decrypted[:]) {
		t.Fatal("Decrypt( Encrypt( ptext ) ) != ptext: Ciphertext decryption with the same key must result in the original plaintext!")
	}

}
Example #6
0
// TestCBCPKCS7Encrypt_EmptyPlaintext encrypts and pad an empty ptext. Verifying as well that the ciphertext length is as expected.
func TestCBCPKCS7Encrypt_EmptyPlaintext(t *testing.T) {

	key := make([]byte, primitives.AESKeyLength)
	rand.Reader.Read(key)

	t.Log("Generated key: ", key)

	var emptyPlaintext = []byte("")
	t.Log("Plaintext length: ", len(emptyPlaintext))

	ciphertext, encErr := primitives.CBCPKCS7Encrypt(key, emptyPlaintext)
	if encErr != nil {
		t.Fatalf("Error encrypting '%v'", encErr)
	}

	// Expected ciphertext length: primitives.AESKeyLength (=32)
	// As part of the padding, at least one block gets encrypted (while the first block is the IV)
	const expectedLength = aes.BlockSize + aes.BlockSize
	if len(ciphertext) != expectedLength {
		t.Fatalf("Wrong ciphertext length. Expected %d, recieved %d", expectedLength, len(ciphertext))
	}

	t.Log("Ciphertext length: ", len(ciphertext))
	t.Log("Cipher: ", ciphertext)
}
Example #7
0
// TestCBCPKCS7EncryptCBCDecrypt_ExpectingCorruptMessage verifies that CBCDecrypt can decrypt the unpadded
// version of the ciphertext, of a message of BlockSize length.
func TestCBCPKCS7EncryptCBCDecrypt_ExpectingCorruptMessage(t *testing.T) {

	// One of the purposes of this test is to also document and clarify the expected behavior, i.e., that an extra
	// block is appended to the message at the padding stage, as per the spec of PKCS#7 v1.5 [see RFC-2315 p.21]
	key := make([]byte, primitives.AESKeyLength)
	rand.Reader.Read(key)

	//                  0123456789ABCDEF
	var ptext = []byte("a 16 byte messag")

	encrypted, encErr := primitives.CBCPKCS7Encrypt(key, ptext)
	if encErr != nil {
		t.Fatalf("Error encrypting ptext %v", encErr)
	}

	decrypted, dErr := primitives.CBCDecrypt(key, encrypted)
	if dErr != nil {
		t.Fatalf("Error encrypting ptext %v, %v", dErr, decrypted)
	}

	if string(ptext[:]) != string(decrypted[:aes.BlockSize]) {
		t.Log("ptext: ", ptext)
		t.Log("decrypted: ", decrypted[:aes.BlockSize])
		t.Fatal("Encryption->Decryption with same key should result in original ptext")
	}

	if !bytes.Equal(decrypted[aes.BlockSize:], bytes.Repeat([]byte{byte(aes.BlockSize)}, aes.BlockSize)) {
		t.Fatal("Expected extra block with padding in encrypted ptext", decrypted)
	}

}
Example #8
0
func TestCBCPKCS7Encrypt_EmptyText(t *testing.T) {
	// Encrypt an empty message. Mainly to document
	// a borderline case. Checking as well that the
	// cipher length is as expected.

	key := make([]byte, 32)
	rand.Reader.Read(key)

	t.Log("Generated key: ", key)

	var msg = []byte("")
	t.Log("Message length: ", len(msg))

	cipher, encErr := primitives.CBCPKCS7Encrypt(key, msg)
	if encErr != nil {
		t.Fatalf("Error encrypting message %v", encErr)
	}

	t.Log("Cipher length: ", len(cipher))

	// expected cipher length: 32
	// with padding, at least one block gets encrypted
	// the first block is the IV
	var expectedLength = aes.BlockSize + aes.BlockSize

	if len(cipher) != expectedLength {
		t.Fatalf("Cipher length is wrong. Expected %d, got %d",
			expectedLength, len(cipher))
	}
	t.Log("Cipher: ", cipher)
}
func (client *clientImpl) encryptTxVersion1_1(tx *obc.Transaction) error {
	// client.enrollChainKey is an AES key represented as byte array
	enrollChainKey := client.enrollChainKey.([]byte)

	// Derive key
	txKey := primitives.HMAC(enrollChainKey, tx.Nonce)

	//	client.log.Info("Deriving from :", utils.EncodeBase64(client.node.enrollChainKey))
	//	client.log.Info("Nonce  ", utils.EncodeBase64(tx.Nonce))
	//	client.log.Info("Derived key  ", utils.EncodeBase64(txKey))

	// Encrypt Payload
	payloadKey := primitives.HMACAESTruncated(txKey, []byte{1})
	encryptedPayload, err := primitives.CBCPKCS7Encrypt(payloadKey, tx.Payload)
	if err != nil {
		return err
	}
	tx.Payload = encryptedPayload

	// Encrypt ChaincodeID
	chaincodeIDKey := primitives.HMACAESTruncated(txKey, []byte{2})
	encryptedChaincodeID, err := primitives.CBCPKCS7Encrypt(chaincodeIDKey, tx.ChaincodeID)
	if err != nil {
		return err
	}
	tx.ChaincodeID = encryptedChaincodeID

	// Encrypt Metadata
	if len(tx.Metadata) != 0 {
		metadataKey := primitives.HMACAESTruncated(txKey, []byte{3})
		encryptedMetadata, err := primitives.CBCPKCS7Encrypt(metadataKey, tx.Metadata)
		if err != nil {
			return err
		}
		tx.Metadata = encryptedMetadata
	}

	return nil
}
Example #10
0
func TestCBCPKCS7EncryptCBCDecrypt_ExpectingCorruptMessage(t *testing.T) {
	// When encrypting a message that does not need padding, i.e. a message
	// whose length is a multiple of the block size, with CBCPKCS7Encrypt, it
	// can be decrypted with CBCDecrypt but the returned message is corrupted.
	//
	// The intend of this test is to document this behaviour for clarity.
	//
	// The reason is that the section 10.3 Note 2 in #PKCS7 states that
	// an extra block is appended to the message for padding. Since this
	// extra block is added when using CBCPKCS7Encrypt for encryption,
	// CBCDecrypt returns the original message plus this extra block.
	//
	// Note:
	// the same applies for messages of arbitrary length.

	key := make([]byte, 32)
	rand.Reader.Read(key)

	//                0123456789ABCDEF
	var msg = []byte("a 16 byte messag")

	encrypted, encErr := primitives.CBCPKCS7Encrypt(key, msg)

	if encErr != nil {
		t.Fatalf("Error encrypting message %v", encErr)
	}

	decrypted, dErr := primitives.CBCDecrypt(key, encrypted)

	if dErr != nil {
		t.Fatalf("Error encrypting message %v, %v", dErr, decrypted)
	}

	if string(msg[:]) != string(decrypted[:aes.BlockSize]) {
		t.Log("msg: ", msg)
		t.Log("decrypted: ", decrypted[:aes.BlockSize])
		t.Fatal("Encryption->Decryption with same key should result in original message")
	}

	if !bytes.Equal(decrypted[aes.BlockSize:], bytes.Repeat([]byte{byte(aes.BlockSize)}, aes.BlockSize)) {
		t.Fatal("Expected extra block with padding in encrypted message", decrypted)
	}

}
Example #11
0
// TestCBCPKCS7Encrypt_CorrectCiphertextLengthCheck verifies that the returned ciphertext lengths are as expected.
func TestCBCPKCS7Encrypt_CorrectCiphertextLengthCheck(t *testing.T) {

	key := make([]byte, aes.BlockSize)
	rand.Reader.Read(key)

	// length of message (in bytes) == aes.BlockSize (16 bytes)
	// The expected cipher length = IV length (1 block) + 1 block message

	var ptext = []byte("0123456789ABCDEF")

	for i := 1; i < aes.BlockSize; i++ {
		ciphertext, err := primitives.CBCPKCS7Encrypt(key, ptext[:i])
		if err != nil {
			t.Fatal("Error encrypting '", ptext, "'")
		}

		expectedLength := aes.BlockSize + aes.BlockSize
		if len(ciphertext) != expectedLength {
			t.Fatalf("Incorrect ciphertext incorrect: expected '%d', received '%d'", expectedLength, len(ciphertext))
		}
	}
}
Example #12
0
func TestCBCPKCS7Encrypt_CipherLengthCorrect(t *testing.T) {
	// Check that the cipher lengths are as expected.
	key := make([]byte, 32)
	rand.Reader.Read(key)

	// length of message < aes.BlockSize (16 bytes)
	// --> expected cipher length = IV length (1 block) + 1 block message
	//     =
	var msg = []byte("0123456789ABCDEF")

	for i := 1; i < aes.BlockSize; i++ {

		cipher, err := primitives.CBCPKCS7Encrypt(key, msg[:i])
		if err != nil {
			t.Fatal("Error encrypting the message.", cipher)
		}

		expectedLength := aes.BlockSize + aes.BlockSize
		if len(cipher) != expectedLength {
			t.Fatalf("Cipher length incorrect: expected %d, got %d", expectedLength, len(cipher))
		}
	}
}
Example #13
0
//EncryptAttributeValue encrypts "attributeValue" using "attributeKey"
func EncryptAttributeValue(attributeKey []byte, attributeValue []byte) ([]byte, error) {
	value := append(attributeValue, padding...)
	return primitives.CBCPKCS7Encrypt(attributeKey, value)
}
Example #14
0
// Generate encrypted extensions to be included into the TCert (TCertIndex, EnrollmentID and attributes).
func (tcap *TCAP) generateExtensions(tcertid *big.Int, tidx []byte, enrollmentCert *x509.Certificate, attrs []*pb.ACAAttribute) ([]pkix.Extension, []byte, error) {
	// For each TCert we need to store and retrieve to the user the list of Ks used to encrypt the EnrollmentID and the attributes.
	extensions := make([]pkix.Extension, len(attrs))

	// Compute preK_1 to encrypt attributes and enrollment ID
	preK1, err := tcap.tca.getPreKFrom(enrollmentCert)
	if err != nil {
		return nil, nil, err
	}

	mac := hmac.New(primitives.GetDefaultHash(), preK1)
	mac.Write(tcertid.Bytes())
	preK0 := mac.Sum(nil)

	// Compute encrypted EnrollmentID
	mac = hmac.New(primitives.GetDefaultHash(), preK0)
	mac.Write([]byte("enrollmentID"))
	enrollmentIDKey := mac.Sum(nil)[:32]

	enrollmentID := []byte(enrollmentCert.Subject.CommonName)
	enrollmentID = append(enrollmentID, Padding...)

	encEnrollmentID, err := primitives.CBCPKCS7Encrypt(enrollmentIDKey, enrollmentID)
	if err != nil {
		return nil, nil, err
	}

	attributeIdentifierIndex := 9
	count := 0
	attrsHeader := make(map[string]int)
	// Encrypt and append attrs to the extensions slice
	for _, a := range attrs {
		count++

		value := []byte(a.AttributeValue)

		//Save the position of the attribute extension on the header.
		attrsHeader[a.AttributeName] = count

		if isEnabledAttributesEncryption() {
			value, err = attributes.EncryptAttributeValuePK0(preK0, a.AttributeName, value)
			if err != nil {
				return nil, nil, err
			}
		}

		// Generate an ObjectIdentifier for the extension holding the attribute
		TCertEncAttributes := asn1.ObjectIdentifier{1, 2, 3, 4, 5, 6, attributeIdentifierIndex + count}

		// Add the attribute extension to the extensions array
		extensions[count-1] = pkix.Extension{Id: TCertEncAttributes, Critical: false, Value: value}
	}

	// Append the TCertIndex to the extensions
	extensions = append(extensions, pkix.Extension{Id: TCertEncTCertIndex, Critical: true, Value: tidx})

	// Append the encrypted EnrollmentID to the extensions
	extensions = append(extensions, pkix.Extension{Id: TCertEncEnrollmentID, Critical: false, Value: encEnrollmentID})

	// Append the attributes header if there was attributes to include in the TCert
	if len(attrs) > 0 {
		headerValue, err := attributes.BuildAttributesHeader(attrsHeader)
		if err != nil {
			return nil, nil, err
		}
		if isEnabledAttributesEncryption() {
			headerValue, err = attributes.EncryptAttributeValuePK0(preK0, attributes.HeaderAttributeName, headerValue)
			if err != nil {
				return nil, nil, err
			}
		}
		extensions = append(extensions, pkix.Extension{Id: TCertAttributesHeaders, Critical: false, Value: headerValue})
	}

	return extensions, preK0, nil
}
Example #15
0
func (tcap *TCAP) createCertificateSet(ctx context.Context, raw []byte, in *pb.TCertCreateSetReq) (*pb.TCertCreateSetResp, error) {
	var attrs = []*pb.ACAAttribute{}
	var err error
	var id = in.Id.Id
	var timestamp = in.Ts.Seconds
	const TCERT_SUBJECT_COMMON_NAME_VALUE string = "Transaction Certificate"

	if in.Attributes != nil && viper.GetBool("aca.enabled") {
		attrs, err = tcap.requestAttributes(id, raw, in.Attributes)
		if err != nil {
			return nil, err
		}
	}

	cert, err := x509.ParseCertificate(raw)
	if err != nil {
		return nil, err
	}

	pub := cert.PublicKey.(*ecdsa.PublicKey)

	r, s := big.NewInt(0), big.NewInt(0)
	r.UnmarshalText(in.Sig.R)
	s.UnmarshalText(in.Sig.S)

	//sig := in.Sig
	in.Sig = nil

	hash := primitives.NewHash()
	raw, _ = proto.Marshal(in)
	hash.Write(raw)
	if ecdsa.Verify(pub, hash.Sum(nil), r, s) == false {
		return nil, errors.New("signature does not verify")
	}

	// Generate nonce for TCertIndex
	nonce := make([]byte, 16) // 8 bytes rand, 8 bytes timestamp
	rand.Reader.Read(nonce[:8])
	binary.LittleEndian.PutUint64(nonce[8:], uint64(in.Ts.Seconds))

	mac := hmac.New(primitives.GetDefaultHash(), tcap.tca.hmacKey)
	raw, _ = x509.MarshalPKIXPublicKey(pub)
	mac.Write(raw)
	kdfKey := mac.Sum(nil)

	num := int(in.Num)
	if num == 0 {
		num = 1
	}

	// the batch of TCerts
	var set []*pb.TCert

	for i := 0; i < num; i++ {
		tcertid := util.GenerateIntUUID()

		// Compute TCertIndex
		tidx := []byte(strconv.Itoa(2*i + 1))
		tidx = append(tidx[:], nonce[:]...)
		tidx = append(tidx[:], Padding...)

		mac := hmac.New(primitives.GetDefaultHash(), kdfKey)
		mac.Write([]byte{1})
		extKey := mac.Sum(nil)[:32]

		mac = hmac.New(primitives.GetDefaultHash(), kdfKey)
		mac.Write([]byte{2})
		mac = hmac.New(primitives.GetDefaultHash(), mac.Sum(nil))
		mac.Write(tidx)

		one := new(big.Int).SetInt64(1)
		k := new(big.Int).SetBytes(mac.Sum(nil))
		k.Mod(k, new(big.Int).Sub(pub.Curve.Params().N, one))
		k.Add(k, one)

		tmpX, tmpY := pub.ScalarBaseMult(k.Bytes())
		txX, txY := pub.Curve.Add(pub.X, pub.Y, tmpX, tmpY)
		txPub := ecdsa.PublicKey{Curve: pub.Curve, X: txX, Y: txY}

		// Compute encrypted TCertIndex
		encryptedTidx, err := primitives.CBCPKCS7Encrypt(extKey, tidx)
		if err != nil {
			return nil, err
		}

		extensions, preK0, err := tcap.generateExtensions(tcertid, encryptedTidx, cert, attrs)

		if err != nil {
			return nil, err
		}

		spec := NewDefaultPeriodCertificateSpecWithCommonName(id, TCERT_SUBJECT_COMMON_NAME_VALUE, tcertid, &txPub, x509.KeyUsageDigitalSignature, extensions...)
		if raw, err = tcap.tca.createCertificateFromSpec(spec, timestamp, kdfKey, false); err != nil {
			Error.Println(err)
			return nil, err
		}

		set = append(set, &pb.TCert{Cert: raw, Prek0: preK0})
	}

	tcap.tca.persistCertificateSet(id, timestamp, nonce, kdfKey)

	return &pb.TCertCreateSetResp{Certs: &pb.CertSet{Ts: in.Ts, Id: in.Id, Key: kdfKey, Certs: set}}, nil
}