在RSA中,明文、密鑰和密文都是數字。加密過程能夠用下列公式:git
加密公式中出現的E
和N
的組合就是公鑰。golang
公式:算法
數字D
和N
組合起來就是RSA的私鑰。編程
N = p x q
(p、q爲質數)。q、q過小容易被破譯,太大會致使計算時間很長。N = 17 x 19 = 323
app
L = lcm(p-1,q-1)
(L是p-1和q-1的最小公倍數)L = lcm(16,18) = 144
koa
1 < E < L
gcd(E,L) = 1
;表示E和L的最大公約數爲1;E = 5,7,11,13,17,19,23,25,29,31
ui
1 < D < L
E x D mod L = 1
D = 29
加密
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)) }
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() }
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() }
在上述的代碼中有體現。
spa
//生成私鑰 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