dushine00 2019-06-28
在RSA中,明文、密钥和密文都是数字。加密过程可以用下列公式:
加密公式中出现的E
和N
的组合就是公钥。
公式:
数字D
和N
组合起来就是RSA的私钥。
N = p x q
(p、q为质数)。q、q太小容易被破译,太大会导致计算时间很长。N = 17 x 19 = 323
L = lcm(p-1,q-1)
(L是p-1和q-1的最小公倍数)L = lcm(16,18) = 144
1 < E < L
gcd(E,L) = 1
;表示E和L的最大公约数为1;E = 5,7,11,13,17,19,23,25,29,31
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() }
在上述的代码中有体现。
//生成私钥 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