// TransactionPreValidation verifies that the transaction is // well formed with the respect to the security layer // prescriptions (i.e. signature verification). func (peer *peerImpl) TransactionPreValidation(tx *obc.Transaction) (*obc.Transaction, error) { if !peer.isInitialized { return nil, utils.ErrNotInitialized } // peer.debug("Pre validating [%s].", tx.String()) peer.debug("Tx confdential level [%s].", tx.ConfidentialityLevel.String()) if tx.Cert != nil && tx.Signature != nil { // Verify the transaction // 1. Unmarshal cert cert, err := utils.DERToX509Certificate(tx.Cert) if err != nil { peer.error("TransactionPreExecution: failed unmarshalling cert [%s] [%s].", err.Error()) return tx, err } // TODO: verify cert // 3. Marshall tx without signature signature := tx.Signature tx.Signature = nil rawTx, err := proto.Marshal(tx) if err != nil { peer.error("TransactionPreExecution: failed marshaling tx [%s] [%s].", err.Error()) return tx, err } tx.Signature = signature // 2. Verify signature ok, err := peer.verify(cert.PublicKey, rawTx, tx.Signature) if err != nil { peer.error("TransactionPreExecution: failed marshaling tx [%s] [%s].", err.Error()) return tx, err } if !ok { return tx, utils.ErrInvalidTransactionSignature } } else { if tx.Cert == nil { return tx, utils.ErrTransactionCertificate } if tx.Signature == nil { return tx, utils.ErrTransactionSignature } } return tx, nil }
// CheckTransaction is used to verify that a transaction // is well formed with the respect to the security layer // prescriptions. To be used for internal verifications. func (client *clientImpl) checkTransaction(tx *obc.Transaction) error { if !client.isInitialized { return utils.ErrNotInitialized } if tx.Cert == nil && tx.Signature == nil { return utils.ErrTransactionMissingCert } if tx.Cert != nil && tx.Signature != nil { // Verify the transaction // 1. Unmarshal cert cert, err := utils.DERToX509Certificate(tx.Cert) if err != nil { client.node.log.Error("Failed unmarshalling cert [%s].", err.Error()) return err } // TODO: verify cert // 3. Marshall tx without signature signature := tx.Signature tx.Signature = nil rawTx, err := proto.Marshal(tx) if err != nil { client.node.log.Error("Failed marshaling tx [%s].", err.Error()) return err } tx.Signature = signature // 2. Verify signature ver, err := client.node.verify(cert.PublicKey, rawTx, tx.Signature) if err != nil { client.node.log.Error("Failed marshaling tx [%s].", err.Error()) return err } if ver { return nil } return utils.ErrInvalidTransactionSignature } return utils.ErrTransactionMissingCert }
func (client *clientImpl) encryptTx(tx *obc.Transaction) error { if len(tx.Nonce) == 0 { return errors.New("Failed encrypting payload. Invalid nonce.") } // Derive key txKey := utils.HMAC(client.node.enrollChainKey, tx.Nonce) // client.node.log.Info("Deriving from :", utils.EncodeBase64(client.node.enrollChainKey)) // client.node.log.Info("Nonce ", utils.EncodeBase64(tx.Nonce)) // client.node.log.Info("Derived key ", utils.EncodeBase64(txKey)) // Encrypt Payload payloadKey := utils.HMACTruncated(txKey, []byte{1}, utils.AESKeyLength) encryptedPayload, err := utils.CBCPKCS7Encrypt(payloadKey, tx.Payload) if err != nil { return err } tx.Payload = encryptedPayload // Encrypt ChaincodeID chaincodeIDKey := utils.HMACTruncated(txKey, []byte{2}, utils.AESKeyLength) encryptedChaincodeID, err := utils.CBCPKCS7Encrypt(chaincodeIDKey, tx.ChaincodeID) if err != nil { return err } tx.ChaincodeID = encryptedChaincodeID // Encrypt Metadata if len(tx.Metadata) != 0 { metadataKey := utils.HMACTruncated(txKey, []byte{3}, utils.AESKeyLength) encryptedMetadata, err := utils.CBCPKCS7Encrypt(metadataKey, tx.Metadata) if err != nil { return err } tx.Metadata = encryptedMetadata } client.node.log.Debug("Encrypted ChaincodeID [%s].", utils.EncodeBase64(tx.ChaincodeID)) client.node.log.Debug("Encrypted Payload [%s].", utils.EncodeBase64(tx.Payload)) client.node.log.Debug("Encrypted Metadata [%s].", utils.EncodeBase64(tx.Metadata)) return nil }
// TransactionPreValidation verifies that the transaction is // well formed with the respect to the security layer // prescriptions (i.e. signature verification). If this is the case, // the method prepares the transaction to be executed. func (validator *validatorImpl) TransactionPreExecution(tx *obc.Transaction) (*obc.Transaction, error) { if !validator.isInitialized { return nil, utils.ErrNotInitialized } validator.peer.node.log.Debug("Pre executing [%s].", tx.String()) validator.peer.node.log.Debug("Tx confdential level [%s].", tx.ConfidentialityLevel.String()) switch tx.ConfidentialityLevel { case obc.ConfidentialityLevel_PUBLIC: validator.peer.node.log.Debug("Deep cloning.") // Nothing to do here. Clone tx. clone, err := validator.deepCloneTransaction(tx) if err != nil { validator.peer.node.log.Error("Failed deep cloning [%s].", err.Error()) return nil, err } return clone, nil case obc.ConfidentialityLevel_CONFIDENTIAL: validator.peer.node.log.Debug("Clone and Decrypt.") // Clone the transaction and decrypt it newTx, err := validator.decryptTx(tx) if err != nil { validator.peer.node.log.Error("Failed decrypting [%s].", err.Error()) return nil, err } // TODO: Validate confidentiality level. Must be the same on tx and newTx.Spec return newTx, nil default: return nil, utils.ErrInvalidConfidentialityLevel } }
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 := utils.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 := utils.HMACTruncated(txKey, []byte{1}, utils.AESKeyLength) encryptedPayload, err := utils.CBCPKCS7Encrypt(payloadKey, tx.Payload) if err != nil { return err } tx.Payload = encryptedPayload // Encrypt ChaincodeID chaincodeIDKey := utils.HMACTruncated(txKey, []byte{2}, utils.AESKeyLength) encryptedChaincodeID, err := utils.CBCPKCS7Encrypt(chaincodeIDKey, tx.ChaincodeID) if err != nil { return err } tx.ChaincodeID = encryptedChaincodeID // Encrypt Metadata if len(tx.Metadata) != 0 { metadataKey := utils.HMACTruncated(txKey, []byte{3}, utils.AESKeyLength) encryptedMetadata, err := utils.CBCPKCS7Encrypt(metadataKey, tx.Metadata) if err != nil { return err } tx.Metadata = encryptedMetadata } return nil }
func (client *clientImpl) encryptTx(tx *obc.Transaction) error { if tx.Nonce == nil || len(tx.Nonce) == 0 { return errors.New("Failed encrypting payload. Invalid nonce.") } // Derive key txKey := utils.HMAC(client.node.enrollChainKey, tx.Nonce) // client.node.log.Info("Deriving from :", utils.EncodeBase64(client.node.enrollChainKey)) // client.node.log.Info("Nonce ", utils.EncodeBase64(tx.Nonce)) // client.node.log.Info("Derived key ", utils.EncodeBase64(txKey)) // Encrypt using the derived key payloadKey := utils.HMACTruncated(txKey, []byte{1}, utils.AESKeyLength) encryptedPayload, err := utils.CBCPKCS7Encrypt(payloadKey, tx.Payload) if err != nil { return err } tx.EncryptedPayload = encryptedPayload tx.Payload = nil chaincodeIDKey := utils.HMACTruncated(txKey, []byte{2}, utils.AESKeyLength) rawChaincodeID, err := proto.Marshal(tx.ChaincodeID) if err != nil { return err } tx.EncryptedChaincodeID, err = utils.CBCPKCS7Encrypt(chaincodeIDKey, rawChaincodeID) if err != nil { return err } tx.ChaincodeID = nil client.node.log.Debug("Encrypted Payload [%s].", utils.EncodeBase64(tx.EncryptedPayload)) client.node.log.Debug("Encrypted ChaincodeID [%s].", utils.EncodeBase64(tx.EncryptedChaincodeID)) return nil }
func (client *clientImpl) encryptTxVersion1_2(tx *obc.Transaction) error { // Create (PK_C,SK_C) pair ccPrivateKey, err := client.eciesSPI.NewPrivateKey(rand.Reader, conf.GetDefaultCurve()) if err != nil { client.error("Failed generate chaincode keypair: [%s]", err) return err } // Prepare message to the validators var ( stateKey []byte privBytes []byte ) switch tx.Type { case obc.Transaction_CHAINCODE_NEW: // Prepare chaincode stateKey and privateKey stateKey, err = utils.GenAESKey() if err != nil { client.error("Failed creating state key: [%s]", err) return err } privBytes, err = client.eciesSPI.SerializePrivateKey(ccPrivateKey) if err != nil { client.error("Failed serializing chaincode key: [%s]", err) return err } break case obc.Transaction_CHAINCODE_QUERY: // Prepare chaincode stateKey and privateKey stateKey = utils.HMACTruncated(client.queryStateKey, append([]byte{6}, tx.Nonce...), utils.AESKeyLength) privBytes, err = client.eciesSPI.SerializePrivateKey(ccPrivateKey) if err != nil { client.error("Failed serializing chaincode key: [%s]", err) return err } break case obc.Transaction_CHAINCODE_EXECUTE: // Prepare chaincode stateKey and privateKey stateKey = make([]byte, 0) privBytes, err = client.eciesSPI.SerializePrivateKey(ccPrivateKey) if err != nil { client.error("Failed serializing chaincode key: [%s]", err) return err } break } // Encrypt message to the validators cipher, err := client.eciesSPI.NewAsymmetricCipherFromPublicKey(client.chainPublicKey) if err != nil { client.error("Failed creating new encryption scheme: [%s]", err) return err } msgToValidators, err := asn1.Marshal(chainCodeValidatorMessage1_2{privBytes, stateKey}) if err != nil { client.error("Failed preparing message to the validators: [%s]", err) return err } encMsgToValidators, err := cipher.Process(msgToValidators) if err != nil { client.error("Failed encrypting message to the validators: [%s]", err) return err } tx.ToValidators = encMsgToValidators // Encrypt the rest of the fields // Init with chainccode pk cipher, err = client.eciesSPI.NewAsymmetricCipherFromPublicKey(ccPrivateKey.GetPublicKey()) if err != nil { client.error("Failed initiliazing encryption scheme: [%s]", err) return err } // Encrypt chaincodeID using pkC encryptedChaincodeID, err := cipher.Process(tx.ChaincodeID) if err != nil { client.error("Failed encrypting chaincodeID: [%s]", err) return err } tx.ChaincodeID = encryptedChaincodeID // Encrypt payload using pkC encryptedPayload, err := cipher.Process(tx.Payload) if err != nil { client.error("Failed encrypting payload: [%s]", err) return err } tx.Payload = encryptedPayload // Encrypt metadata using pkC if len(tx.Metadata) != 0 { encryptedMetadata, err := cipher.Process(tx.Metadata) if err != nil { client.error("Failed encrypting metadata: [%s]", err) return err } tx.Metadata = encryptedMetadata } return nil }
func getAuthorisedAddresses(tx *protos.Transaction) ([]string, *protos.ChaincodeID) { // TODO fetch address from chaincode deployment tx return []string{"address1", "address2"}, tx.GetChaincodeID() }