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 }