RSA
RSA加密
在RSA中,明文、密钥和密文都是数字。加密过程可以用下列公式:
加密公式中出现的E
和N
的组合就是公钥。
RSA解密
公式:
数字D
和N
组合起来就是RSA的私钥。
生成密钥对
- 求N
N = p x q
(p、q为质数)。q、q太小容易被破译,太大会导致计算时间很长。N = 17 x 19 = 323
- 求L(L是仅在生成密钥对的过程中使用的数)
L = lcm(p-1,q-1)
(L是p-1和q-1的最小公倍数)L = lcm(16,18) = 144
- 求E
1 < E < L
gcd(E,L) = 1
;表示E和L的最大公约数为1;E = 5,7,11,13,17,19,23,25,29,31
- 求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()
}
其他应用
公钥生成地址
在上述的代码中有体现。
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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。