【go密码学】-非对称加密算法

jincheng828 · · 2045 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

RSA

RSA加密

在RSA中,明文、密钥和密文都是数字。加密过程可以用下列公式:

clipboard.png
加密公式中出现的EN的组合就是公钥。

RSA解密

公式:

clipboard.png
数字DN组合起来就是RSA的私钥。

生成密钥对

  1. 求N

N = p x q (p、q为质数)。q、q太小容易被破译,太大会导致计算时间很长。
N = 17 x 19 = 323

  1. 求L(L是仅在生成密钥对的过程中使用的数)

L = lcm(p-1,q-1) (L是p-1和q-1的最小公倍数)
L = lcm(16,18) = 144

  1. 求E

1 < E < L
gcd(E,L) = 1 ;表示E和L的最大公约数为1;
E = 5,7,11,13,17,19,23,25,29,31

  1. 求D

1 < D < L
E x D mod L = 1
D = 29

go应用

package main
import (
    "encoding/pem"
    "crypto/x509"
    "crypto/rsa"
    "crypto/rand"
    "fmt"
)

//RSA对称性加密
//公钥加密、私钥解密

var priKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCe8zGb4UAMg2A63pH+/W145hHvYQPJlkX6OfzJ1215htCI6Pyh
2TdHRrDqVU6wP609ao9tLxRsbbXrajBGXiq2ijRX7AKrsVdhYi2J+B2q/CrsH5CD
Ka16YCVPPwf/oZDz/hxrcjZjhOoSIZupY3/xzOBTTjcVcvWbTxGw0wOm6wIDAQAB
AoGABrVg7KFPILgSwalPJCHyEt4y95VyoXl0LqFv59ztw+lKt9yNfQ875Ag5w0oi
bhHh7+ulbghEpmbi/LKYov+qccTQMCz4PW1g85LrUYI5PaGKQfsTAWldQeV/mxCk
mimCk8bahoWPX4i2fnyFdCCn7f3kL8RqRp4NXu2En2gJkPECQQDL3QZrRBpxuE8L
vgMPNew+II3XtiMzsXc/EwHpAT2hY/pOXt0pvtGfAU2d1JSzmHlBfqPkhr2S0obE
PpdsXyG3AkEAx5mt8rsDflY8vRYU7Xao0+Smt+9ujMhvtzzS9W62VCUU8xc0UG+x
umgxofSOedkoaR7k2jqFYYbC1CrwPyAUbQJBALle2R9gZctSFE5REOcb2R0E7PVg
oNG4ZP3tgqckga3nAwuQJvp2kJVM0g7Z5f0If/mV9eEuw+JlnDWF1JquRjECQQCi
ZrT0eRsnkO0MgEn4yAInnbPUlphhLbhP48pVbYYmQqGgBHJJPAfkfmBbwMqn83uA
xGU59kGOD4K39FPTWLulAkAngU3Yv8vYmZKcYXuc/TZjxa0sMuRVroWO6ciW81so
+sFpf0SM9Ysgf/nKtux7juJABCfF1ffDQdKwederSMOc
-----END RSA PRIVATE KEY-----`)

//声明公钥
//公钥可以公开给所有人使用,可以用作加密,可以用作验签
var pubKey = []byte(`-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCe8zGb4UAMg2A63pH+/W145hHv
YQPJlkX6OfzJ1215htCI6Pyh2TdHRrDqVU6wP609ao9tLxRsbbXrajBGXiq2ijRX
7AKrsVdhYi2J+B2q/CrsH5CDKa16YCVPPwf/oZDz/hxrcjZjhOoSIZupY3/xzOBT
TjcVcvWbTxGw0wOm6wIDAQAB
-----END PUBLIC KEY-----`)

//RSA加密算法
func RSAEncrypt(origData []byte) []byte {
    //通过公钥加密
    block,_:=pem.Decode(pubKey)
    //解析公钥
    pubInterface,_:=x509.ParsePKIXPublicKey(block.Bytes)
    //加载公钥
    pub:=pubInterface.(*rsa.PublicKey)
    //利用公钥pub加密
    bits,_:=rsa.EncryptPKCS1v15(rand.Reader,pub,origData)
    //返回密文
    return bits
}

//RSA解密
func RSADecrypt(cipherTxt []byte) []byte {
    //通过私钥解密
    block,_:=pem.Decode(priKey)
    //解析私钥
    pri,_:=x509.ParsePKCS1PrivateKey(block.Bytes)
    //解密
    bits,_:=rsa.DecryptPKCS1v15(rand.Reader,pri,cipherTxt)
    //返回明文
    return bits
}

func main() {
    //加密
    cipher:=RSAEncrypt([]byte("hello zhaoyingkui "))
    fmt.Println(cipher)

    //解密
    plain:=RSADecrypt(cipher)
    fmt.Println(string(plain))
}

椭圆曲线

go生成钱包应用

package main

import (
    "crypto/ecdsa"
    "crypto/elliptic"
    "crypto/rand"
    "log"
    "fmt"
    "crypto/sha256"
    "golang.org/x/crypto/ripemd160"
    "bytes"
    "encoding/base64"
)

type Wallet struct {
    //1.私钥
    PrivateKey ecdsa.PrivateKey
    //2.公钥
    PublicKey [] byte
}

func NewWallet() *Wallet {
    privateKey, publicKey := newKeyPair()
    //fmt.Println("privateKey:", privateKey, ",publicKey:", publicKey)

    fmt.Println("公钥为:", base64.StdEncoding.EncodeToString(publicKey))

    fmt.Println("私钥为:", privateKey)
    return &Wallet{privateKey, publicKey}
}

//通过私钥产生公钥
func newKeyPair() (ecdsa.PrivateKey, []byte) {
    /*
    elliptic:椭圆
    curve:曲线
    ecdsa:elliptic curve  digital signature algorithm,椭圆曲线数字签名算法
        比特币使用SECP256K1算法,p256是ecdsa算法中的一种

    ecc:椭圆曲线加密
    dsa:
     */
    //椭圆加密
    curve := elliptic.P256() //椭圆加密算法,得到一个椭圆曲线值,全称:SECP256k1
    private, err := ecdsa.GenerateKey(curve, rand.Reader)
    //fmt.Println("--------私钥:", private)
    //fmt.Printf("%T\n", private)
    if err != nil {
        log.Panic(err)
    }
    //公钥,就是
    pubKey := append(private.PublicKey.X.Bytes(), private.PublicKey.Y.Bytes()...)

    return *private, pubKey
}

/*
两次sha256,1次160
然后version+hash
 */
func (w *Wallet) GetAddress() [] byte {
    //1.先将公钥进行一次hash256
    ripemd160Hash := w.Ripemd160Hash(w.PublicKey)

    version_ripemd160Hash := append([]byte{version}, ripemd160Hash...)

    checkSumBytes := CheckSum(version_ripemd160Hash)

    bytes := append(version_ripemd160Hash, checkSumBytes...)
    return Base58Encode(bytes)
}

func (w *Wallet) Ripemd160Hash(publicKey [] byte) []byte {
    //1.256
    hash256 := sha256.New()
    hash256.Write(publicKey)
    hash := hash256.Sum(nil)

    //2.160
    ripemd := ripemd160.New()
    ripemd.Write(hash)

    return ripemd.Sum(nil)
}

const version = byte(0x00)
const addressChecksumLen = 4

func CheckSum(b [] byte) []byte {
    //2次256hash
    hash1 := sha256.Sum256(b)
    hash2 := sha256.Sum256(hash1[:])
    return hash2[:addressChecksumLen]

}

//判断地址是否有效
func IsValidForAddress(address []byte) bool {

    version_public_checksumBytes := Base58Decode(address)
    fmt.Println("检验version_public_checksumBytes:", version_public_checksumBytes)
    checkSumBytes := version_public_checksumBytes[len(version_public_checksumBytes)-addressChecksumLen:]
    fmt.Println("检验checkSumBytes:", checkSumBytes)
    version_ripemd160 := version_public_checksumBytes[:len(version_public_checksumBytes)-addressChecksumLen]
    fmt.Println("检验version_ripemd160:", version_ripemd160)
    checkBytes := CheckSum(version_ripemd160)
    fmt.Println("检验checkBytes:", checkBytes)
    if bytes.Compare(checkSumBytes, checkBytes) == 0 {
        return true
    }
    return false
}

func Base58Encode(address []byte) []byte {
    // 未实现功能,后续补上
    return address
}

func Base58Decode(address []byte) []byte {
    // 未实现功能,后续补上
    return address
}

func main(){
    NewWallet()
}

其他应用

公钥生成地址

在上述的代码中有体现。
clipboard.png

openssl

//生成私钥
openssl genrsa -out rsa_private_key.pem 1024

//将私钥做pkcs8的转码
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM

//通过私钥生成公钥
openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:jincheng828

查看原文:【go密码学】-非对称加密算法

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2045 次点击  
加入收藏 微博
被以下专栏收入,发现更多相似内容
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传