Skip to content

Commit

Permalink
fix(weaver): usage of weak PRNG hyperledger#2765 issue solve edit
Browse files Browse the repository at this point in the history
  • Loading branch information
KaganCanSit committed Nov 27, 2023
1 parent e171d15 commit d6a55f4
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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: <root cert> -> <int cert 0> -> <int cert 1> -> ......
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: <root cert> -> <int cert 0> -> <int cert 1> -> ......
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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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")
}
Expand All @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit d6a55f4

Please sign in to comment.