Skip to content

Instantly share code, notes, and snippets.

@Shitaibin
Created September 23, 2019 08:59
Show Gist options
  • Save Shitaibin/214193495ae249266b67fb867dcff24b to your computer and use it in GitHub Desktop.
Save Shitaibin/214193495ae249266b67fb867dcff24b to your computer and use it in GitHub Desktop.
CGO panic memory vailation
// SM2Sign signs
func SM2Sign(signKey interface{}, msg []byte) ([]byte, error) {
	sm2Eckey := signKey.(*Sm2EcKey)

	hash := sm3.New()
	hash.Write(msg)
	h := hash.Sum(nil)

	sig := make([]byte, 128, 128)
	var sigLength uint32
	var csigLength C.uint
	res := C.SM2Sign(C.int(0), unsafe.Pointer(&h[0]), C.int(len(h)),
		unsafe.Pointer(&sig[0]), &csigLength, unsafe.Pointer(sm2Eckey.ecKey)) // <-- sm2Eckey.ecKey 为0

	sigLength = uint32(csigLength)
	if res == 0 {
		return nil, fmt.Errorf("SM2Sign error")
	}

	return sig[:sigLength], nil
}

panic 栈:

github.com/hyperledger/fabric/sm/sm2._Cfunc_SM2Sign(0x0, 0xc004fe2bc0, 0x20, 0xc017bd6c00, 0xc00774c4b8, 0x7f8d38000f90, 0x0) ,最后一个参数为0,
/**
 * Computes ECDSA signature of a given hash value using the supplied private key
 * [IN] type:    this parameter is ignored
 * [IN] dgst:    pointer to the hash value to sign
 * [IN] dLen:    length of the hash value
 * [OUT] sig:    buffer to hold the DER encoded signature. sig must point to ECDSA_size(eckey) bytes of memory.
 * [OUT]sigLen:  pointer to the length of the returned signature
 * [IN]eckey:    EC_KEY object containing a private EC key
 * [RET] int:    return 1 on success and 0 otherwise
 */
 EXPORTDLL int SM2Sign(int type, void* dgst, int dLen, void* sig, unsigned int* sigLen, void * eckey)

最后1个参数不应该为0。

func (s *sm2Signer) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) {
	keyBytes, _ := k.Bytes()

	key, err := sm2.LoadSM2PrivKeyFromBytes(keyBytes) // 获取key
	if err != nil {
		return nil, err
	}
	defer sm2.FreeSm2EcKey(key) // 退出时释放C资源
	sig, err := sm2.SM2Sign(key, digest)
	return sig, err
}

func LoadSM2PrivKeyFromBytes(priv []byte) (*Sm2EcKey, error) {
	sm2EcKey := &Sm2EcKey{}
	sm2EcKey.ecKey = C.LoadSM2PrivKeyFromBytes(unsafe.Pointer(&priv[0]), C.int(len(priv)))
	if sm2EcKey.ecKey == nil { // ecKey为nil时会返回错误
		return nil, fmt.Errorf("LoadSM2PrivKeyFromByte error")
	}
	return sm2EcKey, nil
}

type Sm2EcKey struct {
	ecKey *C.EC_KEY // 保存C分配的内存指针
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment