github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/core/access_contoller/cert_member.go (about)

     1  package access_contoller
     2  
     3  import (
     4  	"encoding/hex"
     5  	"encoding/pem"
     6  	"fmt"
     7  	bccrypto "github.com/bigzoro/my_simplechain/core/access_contoller/crypto"
     8  	"github.com/bigzoro/my_simplechain/core/access_contoller/crypto/asym"
     9  	"github.com/bigzoro/my_simplechain/core/access_contoller/crypto/hash"
    10  	bcx509 "github.com/bigzoro/my_simplechain/core/access_contoller/crypto/x509"
    11  	"strings"
    12  )
    13  
    14  type certificateMember struct {
    15  
    16  	// the CommonName field of the certificate
    17  	id string
    18  
    19  	// organization identity who owns this member
    20  	orgId string
    21  
    22  	// the X.509 certificate used for authentication
    23  	cert *bcx509.Certificate
    24  
    25  	// role of this member
    26  	role Role
    27  
    28  	// hash algorithm for chains (It's not the hash algorithm that the certificate uses)
    29  	hashType string
    30  
    31  	// the certificate is compressed or not
    32  	isCompressed bool
    33  }
    34  
    35  // GetPk returns the public key
    36  func (cm *certificateMember) GetPk() bccrypto.PublicKey {
    37  	return cm.cert.PublicKey
    38  }
    39  
    40  // GetMemberId returns the identity of this member (non-uniqueness)
    41  func (cm *certificateMember) GetMemberId() string {
    42  	return cm.id
    43  }
    44  
    45  // GetOrgId returns the organization id which this member belongs to
    46  func (cm *certificateMember) GetOrgId() string {
    47  	return cm.orgId
    48  }
    49  
    50  // GetRole returns roles of this member
    51  func (cm *certificateMember) GetRole() Role {
    52  	return cm.role
    53  }
    54  
    55  // GetUid returns the identity of this member (unique)
    56  func (cm *certificateMember) GetUid() string {
    57  	return hex.EncodeToString(cm.cert.SubjectKeyId)
    58  }
    59  
    60  // Verify verifies a signature over some message using this member
    61  func (cm *certificateMember) Verify(hashType string, msg []byte, sig []byte) error {
    62  	hashAlgo, err := bcx509.GetHashFromSignatureAlgorithm(cm.cert.SignatureAlgorithm)
    63  	if err != nil {
    64  		return fmt.Errorf("cert member verify failed: get hash from signature algorithm failed: [%s]", err.Error())
    65  	}
    66  	ok, err := cm.cert.PublicKey.VerifyWithOpts(msg, sig, &bccrypto.SignOpts{
    67  		Hash: hashAlgo,
    68  		UID:  bccrypto.CRYPTO_DEFAULT_UID,
    69  	})
    70  	if err != nil {
    71  		return fmt.Errorf("cert member verify signature failed: [%s]", err.Error())
    72  	}
    73  	if !ok {
    74  		return fmt.Errorf("cert member verify signature failed: invalid signature")
    75  	}
    76  	return nil
    77  }
    78  
    79  // GetMember returns Member
    80  func (cm *certificateMember) GetMember() (*Member, error) {
    81  	if cm.isCompressed {
    82  		id, err := GetCertificateIdFromDER(cm.cert.Raw, cm.hashType)
    83  		if err != nil {
    84  			return nil, fmt.Errorf("get pb member failed: [%s]", err.Error())
    85  		}
    86  		return &Member{
    87  			OrgId:      cm.orgId,
    88  			MemberInfo: id,
    89  			MemberType: MemberType_CERT_HASH,
    90  		}, nil
    91  	}
    92  
    93  	certPEM := pem.EncodeToMemory(&pem.Block{Bytes: cm.cert.Raw, Type: "CERTIFICATE"})
    94  	return &Member{
    95  		OrgId:      cm.orgId,
    96  		MemberInfo: certPEM,
    97  		MemberType: MemberType_CERT,
    98  	}, nil
    99  }
   100  
   101  func newCertMemberFromParam(orgId, role, hashType string, isCompressed bool,
   102  	certPEM []byte) (*certificateMember, error) {
   103  	var (
   104  		cert *bcx509.Certificate
   105  		err  error
   106  	)
   107  	certBlock, rest := pem.Decode(certPEM)
   108  	if certBlock == nil {
   109  		cert, err = bcx509.ParseCertificate(rest)
   110  		if err != nil {
   111  			return nil, fmt.Errorf("new cert member failed, invalid certificate")
   112  		}
   113  	} else {
   114  		cert, err = bcx509.ParseCertificate(certBlock.Bytes)
   115  		if err != nil {
   116  			return nil, fmt.Errorf("new cert member failed, invalid certificate")
   117  		}
   118  	}
   119  
   120  	if err = cryptoEngineOption(cert); err != nil {
   121  		return nil, fmt.Errorf("set crypto engine failed, err = %s", err)
   122  	}
   123  
   124  	id, err := bcx509.GetExtByOid(bcx509.OidNodeId, cert.Extensions)
   125  	if err != nil {
   126  		id = []byte(cert.Subject.CommonName)
   127  	}
   128  
   129  	role = strings.ToUpper(role)
   130  
   131  	return &certificateMember{
   132  		id:           string(id),
   133  		orgId:        orgId,
   134  		role:         Role(role),
   135  		cert:         cert,
   136  		hashType:     hashType,
   137  		isCompressed: isCompressed,
   138  	}, nil
   139  }
   140  
   141  func newMemberFromCertPem(orgId, hashType string, certPEM []byte, isCompressed bool) (*certificateMember, error) {
   142  	var member certificateMember
   143  	member.isCompressed = isCompressed
   144  
   145  	var cert *bcx509.Certificate
   146  	var err error
   147  	certBlock, rest := pem.Decode(certPEM)
   148  	if certBlock == nil {
   149  		cert, err = bcx509.ParseCertificate(rest)
   150  		if err != nil {
   151  			return nil, fmt.Errorf("new cert member failed, invalid certificate")
   152  		}
   153  	} else {
   154  		cert, err = bcx509.ParseCertificate(certBlock.Bytes)
   155  		if err != nil {
   156  			return nil, fmt.Errorf("new cert member failed, invalid certificate")
   157  		}
   158  	}
   159  
   160  	if err = cryptoEngineOption(cert); err != nil {
   161  		return nil, fmt.Errorf("set crypto engine failed, err = %s", err)
   162  	}
   163  
   164  	member.hashType = hashType
   165  	member.orgId = orgId
   166  
   167  	orgIdFromCert := ""
   168  	if len(cert.Subject.Organization) > 0 {
   169  		orgIdFromCert = cert.Subject.Organization[0]
   170  	}
   171  	if member.orgId == "" {
   172  		member.orgId = orgIdFromCert
   173  	}
   174  	if orgIdFromCert != member.orgId {
   175  		return nil, fmt.Errorf(
   176  			"setup cert member failed, organization information in certificate "+
   177  				"and in input parameter do not match [certificate: %s, parameter: %s]",
   178  			orgIdFromCert,
   179  			orgId,
   180  		)
   181  	}
   182  
   183  	id, err := bcx509.GetExtByOid(bcx509.OidNodeId, cert.Extensions)
   184  	if err != nil {
   185  		id = []byte(cert.Subject.CommonName)
   186  	}
   187  	member.id = string(id)
   188  	member.cert = cert
   189  	ou := ""
   190  	if len(cert.Subject.OrganizationalUnit) > 0 {
   191  		ou = cert.Subject.OrganizationalUnit[0]
   192  	}
   193  	ou = strings.ToUpper(ou)
   194  	member.role = Role(ou)
   195  	return &member, nil
   196  }
   197  
   198  type signingCertMember struct {
   199  	// Extends Identity
   200  	certificateMember
   201  
   202  	// Sign the message
   203  	sk bccrypto.PrivateKey
   204  }
   205  
   206  // Sign When using certificate, the signature-hash algorithm suite is from the certificate
   207  // and the input hashType is ignored.
   208  func (scm *signingCertMember) Sign(hashType string, msg []byte) ([]byte, error) {
   209  	hashAlgo, err := bcx509.GetHashFromSignatureAlgorithm(scm.cert.SignatureAlgorithm)
   210  	if err != nil {
   211  		return nil, fmt.Errorf("sign failed: invalid algorithm: %s", err.Error())
   212  	}
   213  
   214  	return scm.sk.SignWithOpts(msg, &bccrypto.SignOpts{
   215  		Hash: hashAlgo,
   216  		UID:  bccrypto.CRYPTO_DEFAULT_UID,
   217  	})
   218  }
   219  
   220  // NewCertSigningMember 基于传入的参数新建一个SigningMember
   221  // @param hashType
   222  // @param member
   223  // @param privateKeyPem
   224  // @param password
   225  // @return protocol.SigningMember
   226  // @return error
   227  func NewCertSigningMember(hashType string, member *Member, privateKeyPem,
   228  	password string) (SigningMember, error) {
   229  
   230  	certMember, err := newMemberFromCertPem(member.OrgId, hashType, member.MemberInfo, false)
   231  	if err != nil {
   232  		return nil, err
   233  	}
   234  
   235  	var sk bccrypto.PrivateKey
   236  	//nodeConfig := localconf.ChainMakerConfig.NodeConfig
   237  	//if nodeConfig.P11Config.Enabled {
   238  	//	var handle interface{}
   239  	//	handle, err = getHSMHandle()
   240  	//	if err != nil {
   241  	//		return nil, fmt.Errorf("fail to initialize identity management service: [%v]", err)
   242  	//	}
   243  	//
   244  	//	sk, err = cert.ParseP11PrivKey(handle, []byte(privateKeyPem))
   245  	//	if err != nil {
   246  	//		return nil, fmt.Errorf("fail to initialize identity management service: [%v]", err)
   247  	//	}
   248  	//} else {
   249  	sk, err = asym.PrivateKeyFromPEM([]byte(privateKeyPem), []byte(password))
   250  	if err != nil {
   251  		return nil, err
   252  	}
   253  	//}
   254  
   255  	return &signingCertMember{
   256  		*certMember,
   257  		sk,
   258  	}, nil
   259  }
   260  
   261  // GetCertificateIdFromDER get certificate id from DER
   262  func GetCertificateIdFromDER(certDER []byte, hashType string) ([]byte, error) {
   263  	if certDER == nil {
   264  		return nil, fmt.Errorf("get cert from der certDER == nil")
   265  	}
   266  	id, err := hash.GetByStrType(hashType, certDER)
   267  	if err != nil {
   268  		return nil, err
   269  	}
   270  	return id, nil
   271  }
   272  
   273  // cryptoEngineOption parse public key by CryptoEngine
   274  func cryptoEngineOption(cert *bcx509.Certificate) error {
   275  	pkPem, err := cert.PublicKey.String()
   276  	if err != nil {
   277  		return fmt.Errorf("failed to get public key pem, err = %s", err)
   278  	}
   279  	cert.PublicKey, err = asym.PublicKeyFromPEM([]byte(pkPem))
   280  	if err != nil {
   281  		return fmt.Errorf("failed to parse public key, err = %s", err.Error())
   282  	}
   283  	return nil
   284  }