func (validator *validatorImpl) deepCloneAndDecryptTx1_1(tx *obc.Transaction) (*obc.Transaction, error) { if tx.Nonce == nil || len(tx.Nonce) == 0 { return nil, errors.New("Failed decrypting payload. Invalid nonce.") } // clone tx clone, err := validator.deepCloneTransaction(tx) if err != nil { validator.Errorf("Failed deep cloning [%s].", err.Error()) return nil, err } // Derive root key // client.enrollChainKey is an AES key represented as byte array enrollChainKey := validator.enrollChainKey.([]byte) key := primitives.HMAC(enrollChainKey, clone.Nonce) // validator.log.Infof("Deriving from ", utils.EncodeBase64(validator.peer.node.enrollChainKey)) // validator.log.Infof("Nonce ", utils.EncodeBase64(tx.Nonce)) // validator.log.Infof("Derived key ", utils.EncodeBase64(key)) // validator.log.Infof("Encrypted Payload ", utils.EncodeBase64(tx.EncryptedPayload)) // validator.log.Infof("Encrypted ChaincodeID ", utils.EncodeBase64(tx.EncryptedChaincodeID)) // Decrypt Payload payloadKey := primitives.HMACAESTruncated(key, []byte{1}) payload, err := primitives.CBCPKCS7Decrypt(payloadKey, utils.Clone(clone.Payload)) if err != nil { validator.Errorf("Failed decrypting payload [%s].", err.Error()) return nil, err } clone.Payload = payload // Decrypt ChaincodeID chaincodeIDKey := primitives.HMACAESTruncated(key, []byte{2}) chaincodeID, err := primitives.CBCPKCS7Decrypt(chaincodeIDKey, utils.Clone(clone.ChaincodeID)) if err != nil { validator.Errorf("Failed decrypting chaincode [%s].", err.Error()) return nil, err } clone.ChaincodeID = chaincodeID // Decrypt metadata if len(clone.Metadata) != 0 { metadataKey := primitives.HMACAESTruncated(key, []byte{3}) metadata, err := primitives.CBCPKCS7Decrypt(metadataKey, utils.Clone(clone.Metadata)) if err != nil { validator.Errorf("Failed decrypting metadata [%s].", err.Error()) return nil, err } clone.Metadata = metadata } return clone, nil }
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!") } }
// 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) } } }
// 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!") } }
func TestCBCEncryptCBCPKCS7Decrypt_ExpectingFailure(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 CBCEncrypt, it // cannot be decrypted with CBCPKCS7DEcrypt. // // 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 missing when using CBCEncrypt for encryption, // CBCPKCS7Decrypt fails. key := make([]byte, 32) rand.Reader.Read(key) var msg = []byte("a 16 byte messag") encrypted, encErr := primitives.CBCEncrypt(key, msg) if encErr != nil { t.Fatalf("Error encrypting message %v", encErr) } decrypted, dErr := primitives.CBCPKCS7Decrypt(key, encrypted) if dErr != nil { // expected behaviour, decryption fails. t.Logf("Expected error decrypting message %v, decrypted message = %v", dErr, decrypted) } }
//DecryptAttributeValue decrypts "encryptedValue" using "attributeKey" and return the decrypted value. func DecryptAttributeValue(attributeKey []byte, encryptedValue []byte) ([]byte, error) { value, err := primitives.CBCPKCS7Decrypt(attributeKey, encryptedValue) if err != nil { return nil, err } lenPadding := len(padding) lenValue := len(value) if lenValue < lenPadding { return nil, errors.New("Error invalid value. Decryption verification failed.") } lenWithoutPadding := lenValue - lenPadding if bytes.Compare(padding[0:lenPadding], value[lenWithoutPadding:lenValue]) != 0 { return nil, errors.New("Error generating decryption key for value. Decryption verification failed.") } value = value[0:lenWithoutPadding] return value, nil }
// TestCBCEncryptCBCPKCS7Decrypt_BlockSizeLengthPlaintext verifies that CBCPKCS7Decrypt returns an error // when attempting to decrypt ciphertext of an irreproducible length. func TestCBCEncryptCBCPKCS7Decrypt_BlockSizeLengthPlaintext(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) // 1234567890123456 var ptext = []byte("a 16 byte messag") encrypted, encErr := primitives.CBCEncrypt(key, ptext) if encErr != nil { t.Fatalf("Error encrypting '%s': %v", ptext, encErr) } decrypted, dErr := primitives.CBCPKCS7Decrypt(key, encrypted) if dErr == nil { t.Fatalf("Expected an error decrypting ptext '%s'. Decrypted to '%v'", dErr, decrypted) } }
func (client *clientImpl) getTCertsFromTCA(num int) error { client.debug("Get [%d] certificates from the TCA...", num) // Contact the TCA TCertOwnerKDFKey, certDERs, err := client.callTCACreateCertificateSet(num) if err != nil { client.debug("Failed contacting TCA [%s].", err.Error()) return err } // client.debug("TCertOwnerKDFKey [%s].", utils.EncodeBase64(TCertOwnerKDFKey)) // Store TCertOwnerKDFKey and checks that every time it is always the same key if client.tCertOwnerKDFKey != nil { // Check that the keys are the same equal := bytes.Equal(client.tCertOwnerKDFKey, TCertOwnerKDFKey) if !equal { return errors.New("Failed reciving kdf key from TCA. The keys are different.") } } else { client.tCertOwnerKDFKey = TCertOwnerKDFKey // TODO: handle this situation more carefully if err := client.storeTCertOwnerKDFKey(); err != nil { client.error("Failed storing TCertOwnerKDFKey [%s].", err.Error()) return err } } // Validate the Certificates obtained TCertOwnerEncryptKey := primitives.HMACAESTruncated(client.tCertOwnerKDFKey, []byte{1}) ExpansionKey := primitives.HMAC(client.tCertOwnerKDFKey, []byte{2}) j := 0 for i := 0; i < num; i++ { // DER to x509 x509Cert, err := utils.DERToX509Certificate(certDERs[i].Cert) if err != nil { client.debug("Failed parsing certificate [% x]: [%s].", certDERs[i].Cert, err) continue } // Handle Critical Extenstion TCertEncTCertIndex tCertIndexCT, err := utils.GetCriticalExtension(x509Cert, utils.TCertEncTCertIndex) if err != nil { client.error("Failed getting extension TCERT_ENC_TCERTINDEX [% x]: [%s].", err) continue } // Verify certificate against root if _, err := utils.CheckCertAgainRoot(x509Cert, client.tcaCertPool); err != nil { client.warning("Warning verifing certificate [%s].", err.Error()) continue } // Verify public key // 384-bit ExpansionValue = HMAC(Expansion_Key, TCertIndex) // Let TCertIndex = Timestamp, RandValue, 1,2,… // Timestamp assigned, RandValue assigned and counter reinitialized to 1 per batch // Decrypt ct to TCertIndex (TODO: || EnrollPub_Key || EnrollID ?) pt, err := primitives.CBCPKCS7Decrypt(TCertOwnerEncryptKey, tCertIndexCT) if err != nil { client.error("Failed decrypting extension TCERT_ENC_TCERTINDEX [%s].", err.Error()) continue } // Compute ExpansionValue based on TCertIndex TCertIndex := pt // TCertIndex := []byte(strconv.Itoa(i)) client.debug("TCertIndex: [% x].", TCertIndex) mac := hmac.New(primitives.NewHash, ExpansionKey) mac.Write(TCertIndex) ExpansionValue := mac.Sum(nil) // Derive tpk and tsk accordingly to ExapansionValue from enrollment pk,sk // Computable by TCA / Auditor: TCertPub_Key = EnrollPub_Key + ExpansionValue G // using elliptic curve point addition per NIST FIPS PUB 186-4- specified P-384 // Compute temporary secret key tempSK := &ecdsa.PrivateKey{ PublicKey: ecdsa.PublicKey{ Curve: client.enrollPrivKey.Curve, X: new(big.Int), Y: new(big.Int), }, D: new(big.Int), } var k = new(big.Int).SetBytes(ExpansionValue) var one = new(big.Int).SetInt64(1) n := new(big.Int).Sub(client.enrollPrivKey.Params().N, one) k.Mod(k, n) k.Add(k, one) tempSK.D.Add(client.enrollPrivKey.D, k) tempSK.D.Mod(tempSK.D, client.enrollPrivKey.PublicKey.Params().N) // Compute temporary public key tempX, tempY := client.enrollPrivKey.PublicKey.ScalarBaseMult(k.Bytes()) tempSK.PublicKey.X, tempSK.PublicKey.Y = tempSK.PublicKey.Add( client.enrollPrivKey.PublicKey.X, client.enrollPrivKey.PublicKey.Y, tempX, tempY, ) // Verify temporary public key is a valid point on the reference curve isOn := tempSK.Curve.IsOnCurve(tempSK.PublicKey.X, tempSK.PublicKey.Y) if !isOn { client.error("Failed temporary public key IsOnCurve check.") continue } // Check that the derived public key is the same as the one in the certificate certPK := x509Cert.PublicKey.(*ecdsa.PublicKey) if certPK.X.Cmp(tempSK.PublicKey.X) != 0 { client.error("Derived public key is different on X") continue } if certPK.Y.Cmp(tempSK.PublicKey.Y) != 0 { client.error("Derived public key is different on Y") continue } // Verify the signing capability of tempSK err = primitives.VerifySignCapability(tempSK, x509Cert.PublicKey) if err != nil { client.error("Failed verifing signing capability [%s].", err.Error()) continue } // Marshall certificate and secret key to be stored in the database if err != nil { client.error("Failed marshalling private key [%s].", err.Error()) continue } if err := utils.CheckCertPKAgainstSK(x509Cert, interface{}(tempSK)); err != nil { client.error("Failed checking TCA cert PK against private key [%s].", err.Error()) continue } client.debug("Sub index [%d]", j) j++ client.debug("Certificate [%d] validated.", i) client.tCertPool.AddTCert(&tCertImpl{client, x509Cert, tempSK}) } if j == 0 { client.error("No valid TCert was sent") return errors.New("No valid TCert was sent.") } return nil }
func (client *clientImpl) getTCertFromDER(der []byte) (tCert tCert, err error) { if client.tCertOwnerKDFKey == nil { return nil, fmt.Errorf("KDF key not initialized yet") } TCertOwnerEncryptKey := primitives.HMACAESTruncated(client.tCertOwnerKDFKey, []byte{1}) ExpansionKey := primitives.HMAC(client.tCertOwnerKDFKey, []byte{2}) // DER to x509 x509Cert, err := utils.DERToX509Certificate(der) if err != nil { client.debug("Failed parsing certificate [% x]: [%s].", der, err) return } // Handle Critical Extenstion TCertEncTCertIndex tCertIndexCT, err := utils.GetCriticalExtension(x509Cert, utils.TCertEncTCertIndex) if err != nil { client.error("Failed getting extension TCERT_ENC_TCERTINDEX [%s].", err.Error()) return } // Verify certificate against root if _, err = utils.CheckCertAgainRoot(x509Cert, client.tcaCertPool); err != nil { client.warning("Warning verifing certificate [%s].", err.Error()) return } // Verify public key // 384-bit ExpansionValue = HMAC(Expansion_Key, TCertIndex) // Let TCertIndex = Timestamp, RandValue, 1,2,… // Timestamp assigned, RandValue assigned and counter reinitialized to 1 per batch // Decrypt ct to TCertIndex (TODO: || EnrollPub_Key || EnrollID ?) pt, err := primitives.CBCPKCS7Decrypt(TCertOwnerEncryptKey, tCertIndexCT) if err != nil { client.error("Failed decrypting extension TCERT_ENC_TCERTINDEX [%s].", err.Error()) return } // Compute ExpansionValue based on TCertIndex TCertIndex := pt // TCertIndex := []byte(strconv.Itoa(i)) client.debug("TCertIndex: [% x].", TCertIndex) mac := hmac.New(primitives.NewHash, ExpansionKey) mac.Write(TCertIndex) ExpansionValue := mac.Sum(nil) // Derive tpk and tsk accordingly to ExapansionValue from enrollment pk,sk // Computable by TCA / Auditor: TCertPub_Key = EnrollPub_Key + ExpansionValue G // using elliptic curve point addition per NIST FIPS PUB 186-4- specified P-384 // Compute temporary secret key tempSK := &ecdsa.PrivateKey{ PublicKey: ecdsa.PublicKey{ Curve: client.enrollPrivKey.Curve, X: new(big.Int), Y: new(big.Int), }, D: new(big.Int), } var k = new(big.Int).SetBytes(ExpansionValue) var one = new(big.Int).SetInt64(1) n := new(big.Int).Sub(client.enrollPrivKey.Params().N, one) k.Mod(k, n) k.Add(k, one) tempSK.D.Add(client.enrollPrivKey.D, k) tempSK.D.Mod(tempSK.D, client.enrollPrivKey.PublicKey.Params().N) // Compute temporary public key tempX, tempY := client.enrollPrivKey.PublicKey.ScalarBaseMult(k.Bytes()) tempSK.PublicKey.X, tempSK.PublicKey.Y = tempSK.PublicKey.Add( client.enrollPrivKey.PublicKey.X, client.enrollPrivKey.PublicKey.Y, tempX, tempY, ) // Verify temporary public key is a valid point on the reference curve isOn := tempSK.Curve.IsOnCurve(tempSK.PublicKey.X, tempSK.PublicKey.Y) if !isOn { client.error("Failed temporary public key IsOnCurve check.") return nil, fmt.Errorf("Failed temporary public key IsOnCurve check.") } // Check that the derived public key is the same as the one in the certificate certPK := x509Cert.PublicKey.(*ecdsa.PublicKey) if certPK.X.Cmp(tempSK.PublicKey.X) != 0 { client.error("Derived public key is different on X") return nil, fmt.Errorf("Derived public key is different on X") } if certPK.Y.Cmp(tempSK.PublicKey.Y) != 0 { client.error("Derived public key is different on Y") return nil, fmt.Errorf("Derived public key is different on Y") } // Verify the signing capability of tempSK err = primitives.VerifySignCapability(tempSK, x509Cert.PublicKey) if err != nil { client.error("Failed verifing signing capability [%s].", err.Error()) return } // Marshall certificate and secret key to be stored in the database if err != nil { client.error("Failed marshalling private key [%s].", err.Error()) return } if err = utils.CheckCertPKAgainstSK(x509Cert, interface{}(tempSK)); err != nil { client.error("Failed checking TCA cert PK against private key [%s].", err.Error()) return } tCert = &tCertImpl{client, x509Cert, tempSK} return }
func (client *clientImpl) getTCertFromExternalDER(der []byte) (tCert, error) { // DER to x509 x509Cert, err := primitives.DERToX509Certificate(der) if err != nil { client.Debugf("Failed parsing certificate [% x]: [%s].", der, err) return nil, err } // Handle Critical Extension TCertEncTCertIndex tCertIndexCT, err := primitives.GetCriticalExtension(x509Cert, primitives.TCertEncTCertIndex) if err != nil { client.Errorf("Failed getting extension TCERT_ENC_TCERTINDEX [% x]: [%s].", der, err) return nil, err } // Handle Critical Extension TCertEncEnrollmentID TODO validate encEnrollmentID _, err = primitives.GetCriticalExtension(x509Cert, primitives.TCertEncEnrollmentID) if err != nil { client.Errorf("Failed getting extension TCERT_ENC_ENROLLMENT_ID [%s].", err.Error()) return nil, err } // Handle Critical Extension TCertAttributes // for i := 0; i < len(x509Cert.Extensions) - 2; i++ { // attributeExtensionIdentifier := append(utils.TCertEncAttributesBase, i + 9) // _ , err = utils.GetCriticalExtension(x509Cert, attributeExtensionIdentifier) // if err != nil { // client.Errorf("Failed getting extension TCERT_ATTRIBUTE_%s [%s].", i, err.Error()) // // return nil, err // } // } // Verify certificate against root if _, err := primitives.CheckCertAgainRoot(x509Cert, client.tcaCertPool); err != nil { client.Warningf("Warning verifing certificate [% x]: [%s].", der, err) return nil, err } // Try to extract the signing key from the TCert by decrypting the TCertIndex // 384-bit ExpansionValue = HMAC(Expansion_Key, TCertIndex) // Let TCertIndex = Timestamp, RandValue, 1,2,… // Timestamp assigned, RandValue assigned and counter reinitialized to 1 per batch // Decrypt ct to TCertIndex (TODO: || EnrollPub_Key || EnrollID ?) TCertOwnerEncryptKey := primitives.HMACAESTruncated(client.tCertOwnerKDFKey, []byte{1}) ExpansionKey := primitives.HMAC(client.tCertOwnerKDFKey, []byte{2}) pt, err := primitives.CBCPKCS7Decrypt(TCertOwnerEncryptKey, tCertIndexCT) if err == nil { // Compute ExpansionValue based on TCertIndex TCertIndex := pt // TCertIndex := []byte(strconv.Itoa(i)) // TODO: verify that TCertIndex has right format. client.Debugf("TCertIndex: [% x].", TCertIndex) mac := hmac.New(primitives.NewHash, ExpansionKey) mac.Write(TCertIndex) ExpansionValue := mac.Sum(nil) // Derive tpk and tsk accordingly to ExpansionValue from enrollment pk,sk // Computable by TCA / Auditor: TCertPub_Key = EnrollPub_Key + ExpansionValue G // using elliptic curve point addition per NIST FIPS PUB 186-4- specified P-384 // Compute temporary secret key tempSK := &ecdsa.PrivateKey{ PublicKey: ecdsa.PublicKey{ Curve: client.enrollPrivKey.Curve, X: new(big.Int), Y: new(big.Int), }, D: new(big.Int), } var k = new(big.Int).SetBytes(ExpansionValue) var one = new(big.Int).SetInt64(1) n := new(big.Int).Sub(client.enrollPrivKey.Params().N, one) k.Mod(k, n) k.Add(k, one) tempSK.D.Add(client.enrollPrivKey.D, k) tempSK.D.Mod(tempSK.D, client.enrollPrivKey.PublicKey.Params().N) // Compute temporary public key tempX, tempY := client.enrollPrivKey.PublicKey.ScalarBaseMult(k.Bytes()) tempSK.PublicKey.X, tempSK.PublicKey.Y = tempSK.PublicKey.Add( client.enrollPrivKey.PublicKey.X, client.enrollPrivKey.PublicKey.Y, tempX, tempY, ) // Verify temporary public key is a valid point on the reference curve isOn := tempSK.Curve.IsOnCurve(tempSK.PublicKey.X, tempSK.PublicKey.Y) if !isOn { client.Warning("Failed temporary public key IsOnCurve check. This is an foreign certificate.") return &tCertImpl{client, x509Cert, nil, []byte{}}, nil } // Check that the derived public key is the same as the one in the certificate certPK := x509Cert.PublicKey.(*ecdsa.PublicKey) if certPK.X.Cmp(tempSK.PublicKey.X) != 0 { client.Warning("Derived public key is different on X. This is an foreign certificate.") return &tCertImpl{client, x509Cert, nil, []byte{}}, nil } if certPK.Y.Cmp(tempSK.PublicKey.Y) != 0 { client.Warning("Derived public key is different on Y. This is an foreign certificate.") return &tCertImpl{client, x509Cert, nil, []byte{}}, nil } // Verify the signing capability of tempSK err = primitives.VerifySignCapability(tempSK, x509Cert.PublicKey) if err != nil { client.Warning("Failed verifing signing capability [%s]. This is an foreign certificate.", err.Error()) return &tCertImpl{client, x509Cert, nil, []byte{}}, nil } // Marshall certificate and secret key to be stored in the database if err != nil { client.Warningf("Failed marshalling private key [%s]. This is an foreign certificate.", err.Error()) return &tCertImpl{client, x509Cert, nil, []byte{}}, nil } if err = primitives.CheckCertPKAgainstSK(x509Cert, interface{}(tempSK)); err != nil { client.Warningf("Failed checking TCA cert PK against private key [%s]. This is an foreign certificate.", err.Error()) return &tCertImpl{client, x509Cert, nil, []byte{}}, nil } return &tCertImpl{client, x509Cert, tempSK, []byte{}}, nil } client.Warningf("Failed decrypting extension TCERT_ENC_TCERTINDEX [%s]. This is an foreign certificate.", err.Error()) return &tCertImpl{client, x509Cert, nil, []byte{}}, nil }