diff --git a/weaver/core/network/fabric-interop-cc/contracts/interop/certificate_utils.go b/weaver/core/network/fabric-interop-cc/contracts/interop/certificate_utils.go index 71d233ba4f9..e8d21c396fd 100644 --- a/weaver/core/network/fabric-interop-cc/contracts/interop/certificate_utils.go +++ b/weaver/core/network/fabric-interop-cc/contracts/interop/certificate_utils.go @@ -21,13 +21,12 @@ import ( "fmt" "hash" "math/big" - mrand "math/rand" "time" - "golang.org/x/crypto/ed25519" "github.com/ethereum/go-ethereum/crypto/ecies" "github.com/golang/protobuf/proto" "github.com/hyperledger/cacti/weaver/common/protos-go/v2/common" + "golang.org/x/crypto/ed25519" ) const ( @@ -90,9 +89,10 @@ func verifyCaCertificate(cert *x509.Certificate, memberCertificate string) error return nil } -/* This function will receive arguments for exactly one node with the following cert chain assumed: -> -> -> ...... - In a Fabric network, we assume that there are multiple MSPs, each having one or more Root CAs and zero or more Intermediate CAs. - In a Corda network, we assume that there is a single Root CA and Doorman CA, and one or more Node CAs corresponding to nodes. +/* +This function will receive arguments for exactly one node with the following cert chain assumed: -> -> -> ...... +In a Fabric network, we assume that there are multiple MSPs, each having one or more Root CAs and zero or more Intermediate CAs. +In a Corda network, we assume that there is a single Root CA and Doorman CA, and one or more Node CAs corresponding to nodes. */ func verifyCertificateChain(cert *x509.Certificate, certPEMs []string) error { var parentCert *x509.Certificate @@ -148,9 +148,11 @@ func validateCertificateUsingCA(cert *x509.Certificate, signerCACert *x509.Certi return nil } -// Check if 'PublicKey' field in cert is nil -// Fabric certificates contain such keys, whereas Corda certificates contain ED25519 keys (but only in raw form) -// So this check serves to distinguish Corda certificates from Fabric certificates +/* +Check if 'PublicKey' field in cert is nil +Fabric certificates contain such keys, whereas Corda certificates contain ED25519 keys (but only in raw form) +So this check serves to distinguish Corda certificates from Fabric certificates +*/ func getECDSAPublicKeyFromCertificate(cert *x509.Certificate) *ecdsa.PublicKey { if cert.PublicKey != nil { if certPublicKey, isEcdsaKey := cert.PublicKey.(*ecdsa.PublicKey); isEcdsaKey { @@ -207,7 +209,7 @@ func ecdsaVerify(verKey *ecdsa.PublicKey, msgHash, signature []byte) error { return nil } -//Validate Ed25519 signature +// Validate Ed25519 signature func verifyEd25519Signature(pubKey []byte, hashedMessage []byte, signature []byte) error { result := ed25519.Verify(pubKey, hashedMessage, signature) @@ -273,9 +275,6 @@ func encryptWithCert(message []byte, cert *x509.Certificate) ([]byte, error) { pubKey := getECDSAPublicKeyFromCertificate(cert) if pubKey != nil { return encryptWithECDSAPublicKey(message, pubKey) - } else if (cert.RawSubjectPublicKeyInfo != nil && len(cert.RawSubjectPublicKeyInfo) == 44) { // ed25519 public key - // We expect the key to be 44 bytes, but only the last 32 bytes (multiple of 8) comprise the public key - return encryptWithEd25519PublicKey(message, cert.RawSubjectPublicKeyInfo[12:]) } else { return []byte(""), errors.New("Missing or unsupported public key type for encryption") } @@ -293,44 +292,64 @@ func encryptWithECDSAPublicKey(message []byte, pubKey *ecdsa.PublicKey) ([]byte, return []byte(""), errors.New("Missing or invalid ECDSA public key") } -func encryptWithEd25519PublicKey(message []byte, pubKey []byte) ([]byte, error) { - return []byte(""), nil +func generateSecureRandomKey(length int) ([]byte, error) { + key := make([]byte, length) + _, err := rand.Read(key) + if err != nil { + return nil, err + } + return key, nil +} + +func generateHMAC(data, key []byte) ([]byte, error) { + hmacHash := hmac.New(sha256.New, key) + _, err := hmacHash.Write(data) + if err != nil { + return nil, err + } + return hmacHash.Sum(nil), nil } func generateConfidentialInteropPayloadAndHash(message []byte, cert string) ([]byte, error) { // Generate a 16-byte random key for the HMAC - hashKey := make([]byte, 16) - for i := 0; i < 16 ; i++ { - hashKey[i] = byte(mrand.Intn(255)) + hashKey, err := generateSecureRandomKey(16) + if err != nil { + return nil, err } + confidentialPayloadContents := common.ConfidentialPayloadContents{ Payload: message, - Random: hashKey, + Random: hashKey, } confidentialPayloadContentsBytes, err := proto.Marshal(&confidentialPayloadContents) if err != nil { - return []byte(""), err + return nil, err } + x509Cert, err := parseCert(cert) if err != nil { - return []byte(""), err + return nil, err } + encryptedPayload, err := encryptWithCert(confidentialPayloadContentsBytes, x509Cert) if err != nil { - return []byte(""), err + return nil, err + } + + payloadHMAC, err := generateHMAC(message, hashKey) + if err != nil { + return nil, err } - payloadHMAC := hmac.New(sha256.New, hashKey) - payloadHMAC.Write(message) - payloadHMACBytes := payloadHMAC.Sum(nil) confidentialPayload := common.ConfidentialPayload{ EncryptedPayload: encryptedPayload, - HashType: common.ConfidentialPayload_HMAC, - Hash: payloadHMACBytes, + HashType: common.ConfidentialPayload_HMAC, + Hash: payloadHMAC, } + confidentialPayloadBytes, err := proto.Marshal(&confidentialPayload) if err != nil { - return []byte(""), err + return nil, err } return confidentialPayloadBytes, nil } diff --git a/weaver/sdks/corda/src/main/kotlin/org/hyperledger/cacti/weaver/sdk/corda/HashFunctions.kt b/weaver/sdks/corda/src/main/kotlin/org/hyperledger/cacti/weaver/sdk/corda/HashFunctions.kt index fac95b44365..3a5e247823f 100644 --- a/weaver/sdks/corda/src/main/kotlin/org/hyperledger/cacti/weaver/sdk/corda/HashFunctions.kt +++ b/weaver/sdks/corda/src/main/kotlin/org/hyperledger/cacti/weaver/sdk/corda/HashFunctions.kt @@ -9,7 +9,7 @@ package org.hyperledger.cacti.weaver.sdk.corda; import java.util.Base64 import net.corda.core.utilities.OpaqueBytes import net.corda.core.crypto.sha256 -import kotlin.random.Random +import java.security.SecureRandom import org.hyperledger.cacti.weaver.protos.common.asset_locks.AssetLocks.HashMechanism import org.hyperledger.cacti.weaver.imodule.corda.states.sha512 @@ -42,8 +42,9 @@ class HashFunctions { override fun generateRandomPreimage(length: Int) { - val bytes = ByteArray(length) - Random.nextBytes(bytes) + val secureRandom = SecureRandom.getInstanceStrong(); + val bytes = ByteArray(length); + secureRandom.nextBytes(bytes); this.setPreimage(Base64.getEncoder().encodeToString(bytes)); } override fun setPreimage(preImage: String) { diff --git a/weaver/sdks/fabric/interoperation-node-sdk/src/eciesCrypto.js b/weaver/sdks/fabric/interoperation-node-sdk/src/eciesCrypto.js index 297e1e04962..70496955ebd 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/src/eciesCrypto.js +++ b/weaver/sdks/fabric/interoperation-node-sdk/src/eciesCrypto.js @@ -161,7 +161,7 @@ function eciesEncryptMessage(recipientPublicKey, msg, options) { const hKm = bitsToBytes(hmacKeyHash.finalize()); const iv = crypto.randomBytes(IVLength); - const cipher = crypto.createCipheriv("aes-128-ctr", Buffer.from(aesKey), iv); + const cipher = crypto.createCipheriv("aes-256-ctr", Buffer.from(aesKey), iv); const encryptedBytes = cipher.update(msg); const EM = Buffer.concat([iv, encryptedBytes]); const D = hmac(hKm, EM, options);