golang 椭圆曲线加密使用ecdsa

Posted 区块链兄弟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 椭圆曲线加密使用ecdsa相关的知识,希望对你有一定的参考价值。

点击蓝字,轻松关注

来源:简书

原文链接:http://t.cn/RFnWcox

本文约4000字+,阅读(观看)需要23分钟



非对称加密算法有RSA、ECDSA,对极大整数做因数分解的难度决定了RSA算法的可靠性,ECDSA为椭圆曲线加密算法,是基于椭圆方程公式,所以安全性要高于RSA。


这里说下使用ecdsa做签名和校验,并不讲原理;


golang封装的ecdsa目前只有用私钥加密,公钥做校验,没有解密环节;所以目前可以应用于数字签名;


以下为封装:


/**    通过一个随机key创建公钥和私钥    随机key至少为36位 */func getEcdsaKey(randKey string) (*ecdsa.PrivateKey, ecdsa.PublicKey, error){

    var err error

    var prk *ecdsa.PrivateKey
    var puk ecdsa.PublicKey
    var curve elliptic.Curve

    lenth := len(randKey)    if lenth < 224/8 {
        err =errors.New("私钥长度太短,至少为36位!")        return prk,puk,err
    }    if lenth > 521/8 + 8 {
        curve = elliptic.P521()
    }else if lenth > 384/8 + 8 {
        curve = elliptic.P384()
    }else if lenth > 256/8 + 8 {
        curve = elliptic.P256()
    }else if lenth > 224/8 + 8 {
        curve = elliptic.P224()
    }

    prk, err = ecdsa.GenerateKey(curve,strings.NewReader(randKey))    if err != nil {        return prk, puk, err
    }

    puk = prk.PublicKey    return prk, puk, err

}/**    对text加密,text必须是一个hash值,例如md5、sha1等    使用私钥prk    使用随机熵增强加密安全,安全依赖于此熵,randsign    返回加密结果,结果为数字证书r、s的序列化后拼接,然后用hex转换为string */func sign(text []byte,randSign string,prk *ecdsa.PrivateKey) (string, error) {
    r, s, err := ecdsa.Sign(strings.NewReader(randSign), prk, text)    if err != nil {        return "", err
    }
    rt, err := r.MarshalText()    if err != nil {        return "", err
    }
    st, err := s.MarshalText()    if err != nil {        return "", err
    }
    var b bytes.Buffer
    w := gzip.NewWriter(&b)
    defer w.Close()
    _, err = w.Write([]byte(string(rt) + "+" + string(st)))    if err != nil {        return "", err
    }
    w.Flush()    return hex.EncodeToString(b.Bytes()), nil}/**    证书分解    通过hex解码,分割成数字证书r,s */func getSign( signature string) (rint, sint big.Int, err error)  {
    byterun, err := hex.DecodeString(signature)    if err != nil {
        err = errors.New("decrypt error, "+ err.Error())        return
    }
    r, err := gzip.NewReader(bytes.NewBuffer(byterun))    if err !=  nil {
        err = errors.New("decode error,"+err.Error())        return
    }
    defer r.Close()
    buf := make([]byte, 1024)
    count, err := r.Read(buf)    if err != nil {
        fmt.Println("decode = ",err)
        err = errors.New("decode read error," + err.Error())        return
    }
    rs := strings.Split(string(buf[:count]),"+")    if len(rs) != 2 {
        err = errors.New("decode fail")        return
    }
    err = rint.UnmarshalText([]byte(rs[0]))    if err != nil {
        err = errors.New("decrypt rint fail, "+ err.Error())        return
    }
    err = sint.UnmarshalText([]byte(rs[1]))    if err != nil {
        err = errors.New("decrypt sint fail, "+ err.Error())        return
    }    return}/**    校验文本内容是否与签名一致    使用公钥校验签名和文本内容 */func verify(text []byte, signature string, key ecdsa.PublicKey) (bool, error) {

    rint, sint, err :=getSign(signature)    if err != nil {        return false, err
    }
    result := ecdsa.Verify(&key,text,&rint,&sint)    return result, nil}/**    hash加密    使用md5加密 */func hashtext(text, salt string) ([]byte) {

    Md5Inst := md5.New()
    Md5Inst.Write([]byte(text))
    result := Md5Inst.Sum([]byte(salt))    return result
}


func main() {    //随机熵,用于加密安全
    randSign := "20180619zafes"
    //随机key,用于创建公钥和私钥
    randKey := "fb0f7279c18d4394594fc9714797c9680335a320"
    //创建公钥和私钥
    prk, puk, err := getEcdsaKey(randKey)    if err != nil {
        fmt.Println(err)
    }    //hash加密使用md5用到的salt
    salt := "131ilzaw"
    //待加密的明文
    text := "hlloaefaefaefaefaefaefaefhelloaefaefaefaefaefaefaefhelloaefaefaefaefaefaefaef"
    //text1 := "hlloaefaefaefaefaefaefaefhelloaefaefaefaefaefaefaefhelloaefaefaefaefaefaefaef1"

    //hash取值
    htext := hashtext(text,salt)    //htext1 := hashtext(text1,salt)
    //hash值编码输出
    fmt.Println(hex.EncodeToString(htext))    //hash值进行签名
    result, err := sign(htext,randSign,prk)    if err != nil {
        fmt.Println(err)
    }    //签名输出
    fmt.Println(result)    //签名与hash值进行校验
    tmp, err := verify(htext,result,puk)
    fmt.Println(tmp)
}


借鉴使用……


文章发布只为分享区块链技术内容,版权归原作者所有,观点仅代表作者本人,绝不代表区块链兄弟赞同其观点或证实其描述。


猜猜你喜欢


分享 | 2018年度中国区块链专利报告

Fomo3D死亡3分钟:黑客用0.8ETH赢下了10000个ETH


点击“阅读原文”参与区块链问题讨论

以上是关于golang 椭圆曲线加密使用ecdsa的主要内容,如果未能解决你的问题,请参考以下文章

椭圆曲线数字签名算法(ECDSA)

椭圆曲线密码学ECC

Golang 椭圆加密算法实现

椭圆加密算法

如何使用椭圆曲线私钥和 ECDSA 算法签署证书?

Java - 使用 ECDSA(椭圆曲线)创建 XML 数字签名