【go密碼學】-非對稱加密算法

RSA

RSA加密

在RSA中,明文、密鑰和密文都是數字。加密過程能夠用下列公式:git

clipboard.png
加密公式中出現的EN的組合就是公鑰。golang

RSA解密

公式:算法

clipboard.png
數字DN組合起來就是RSA的私鑰。編程

生成密鑰對

  1. 求N

N = p x q (p、q爲質數)。q、q過小容易被破譯,太大會致使計算時間很長。
N = 17 x 19 = 323app

  1. 求L(L是僅在生成密鑰對的過程當中使用的數)

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

  1. 求E

1 < E < L
gcd(E,L) = 1 ;表示E和L的最大公約數爲1;
E = 5,7,11,13,17,19,23,25,29,31ui

  1. 求D

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

代碼1

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))
}

代碼2

package main

import (
    "crypto/rsa"
    "crypto/rand"
    "fmt"
    "crypto/md5"
    "encoding/base64"
    "crypto"
)

//用公鑰加密,私鑰解密
//用私鑰簽名,公鑰驗證
//公鑰是公開的,任何人能夠使用公鑰,私鑰非公開(保存好)

//一,編程實現,公鑰加密,私鑰解密的過程
func crypt() {
    //建立私鑰
    priv, _ := rsa.GenerateKey(rand.Reader, 1024)
    fmt.Println("輸出系統自動產生的私鑰", priv)

    //建立公鑰
    pub := priv.PublicKey

    //準備加密的明文
    org := []byte("hello kongyixueyuan")

    //公鑰加密
    cipherTxt, _ := rsa.EncryptOAEP(md5.New(), rand.Reader, &pub, org, nil)
    //打印密文
    fmt.Println("密文爲:", cipherTxt)
    fmt.Println("密文爲:", base64.StdEncoding.EncodeToString(cipherTxt))

    //用私鑰解密
    plaintext, _ := rsa.DecryptOAEP(md5.New(), rand.Reader, priv, cipherTxt, nil)
    //打印解密後的結果
    fmt.Println("明文爲:", string(plaintext))

}

func main() {
    crypt()
}

橢圓曲線

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.pngspa

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
相關文章
相關標籤/搜索