加密算法之RSA与数字签名

RSA

  • RSA算法是目前应用最广泛的公钥密码体制之一。RSA算法的安全性是给予大整数因子分解的困难性。RSA名字是由三个开发者的姓名首字母组合而得来的,分别是Ron Rivest,Adi Shamir和Leonard Adleman。
  • RSA不仅广泛应用于信息加密传输,同时也广泛应用于数字签名

RSA公私钥对的产生

  1. RSA的加密算法可以用公式来表示: 密文=明文^E modN
  2. 解密算法则表示为:明文=密文^D modN
  3. 上面公式当中的E,D,N组成了公钥,私钥。其中由E和N组成的称为公钥,由D跟N组成的称为私钥

1.求N

  • 首先准备两个很大的质数p跟q,p和q如果太小的话密码容易被破译。N就是p跟q的乘积,公式表示:N=p x q
    • 比如p = 51,q = 43,则N = 51 x 43 = 2193。 N的长度就是密钥的长度,在这里N转换为二进制为:100010010001.总共为12位,在实际应用过程中,经常是1024位,重要的加密过程当中是2048位

2.求L

  • L在RSA的加密和解密过程中都不出现,它只出现在生成密钥对的过程中。Lp-1q-1的最小公倍数
    用lcm(X,Y)来表示“X和Y的最小公倍数”,则L用公式表示为:
    L=lcm(p-1,q-1)
    • 由上面的例子中,L = 50 x 42 = 2100

3.求E

  • E是一个比1大,比L小的数,此外,EL的最大公约数是1。如果用gcd(X,Y)来表示X跟Y的最大公约数,则E和L之间存在下列关系:

1 < E < L

gcd(E,L) = 1

  • 上述例子中我们就要在1~2100,选择一个与2100互质的数,我们随机选择11 ,实际中我们经常选择65537,当我们p跟q这两个质数选择得很大的时候

4.求D

  • D是由数E计算出来的,DEL之间必须具备以下关系:

    1 < D < L

    E X D mod L = 1

    • 这里我们找到一个数191符合以上条件,所以D = 191

5.由N,L,E,D封装公钥和私钥

  • 公钥就是(11,2193),私钥就是(191,2193)

6.加密

要加密的明文转换为二进制后必须是一个小于N的数,我们可以取100,加密使用的公钥是,E = 11,N = 2193,那么由公式:明文^E mod N = 密文

  • 100 ^ 11 mod 2193 = 131,则密文就是131

步骤

  • 保存由命令行产生的一对公钥私钥
var privateKey = []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 publicKey = []byte(`-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCe8zGb4UAMg2A63pH+/W145hHv
YQPJlkX6OfzJ1215htCI6Pyh2TdHRrDqVU6wP609ao9tLxRsbbXrajBGXiq2ijRX
7AKrsVdhYi2J+B2q/CrsH5CDKa16YCVPPwf/oZDz/hxrcjZjhOoSIZupY3/xzOBT
TjcVcvWbTxGw0wOm6wIDAQAB
-----END PUBLIC KEY-----`)
  • 定义功能RSA加密
func RSAEncrypt(orgiData []byte) []byte  {
    //加载公钥
    block,_ :=  pem.Decode(publicKey)
    //解析公钥
    publicInterface,_ := x509.ParsePKIXPublicKey(block.Bytes)
    //加载公钥
    public := publicInterface.(*rsa.PublicKey)
    //利用公钥进行加密
    bits,_ := rsa.EncryptPKCS1v15(rand.Reader,public,orgiData)
    //返回密文
    return bits
}
  • 定义功能RSA解密
func RSADecrypt(cipherText []byte)  []byte {
    //通过私钥解密
    block,_ := pem.Decode(privateKey)
    //解析私钥
    pri,_ := x509.ParsePKCS1PrivateKey(block.Bytes)
    //解密
    bits,_ := rsa.DecryptPKCS1v15(rand.Reader,pri,cipherText)
    return bits
}
  • 在main函数中使用RSA进行加密解密
func main() {
    //加密
    cipher := RSAEncrypt([]byte("hello world"))
    //解密
    origData := RSADecrypt(cipher)
    fmt.Println(string(origData))
}

数字签名

  • 如简单的使用RSA进行数据加密传输有可能会面临中间人攻击
    中间人攻击并没有破译RSA密钥,只是混入了发送者跟接收者得中间,对发送者伪装成接收者,对接收者伪装成发送者的攻击方式。这种攻击可以针对任何公钥密码,相应的密码算法也都正常工作,但是机密性并非在原始的发送方跟接受方建立的。想要防止这种中间人攻击,需要使用到数字签名
  • 数字签名在信息安全,身份认证,数据完整性,不可否认性以及匿名性有着重要作用,签名一样属于公钥密码学。签名是由信息发送方使用私钥进行相应的hash运算,这个hash就是签名,发送信息时将签名和原文信息发送给接收方,接收方若能够使用公钥

RSA签名与验签

func main() {
    //明文,要加密的数据
    msg := "Bob send 10 BTC to Alice"
    msg_hash := sha256.Sum256([]byte(msg))

    //加载私钥
    block,_ := pem.Decode(PrivateKey)
    // 解析
    private_key,_ := x509.ParsePKCS1PrivateKey(block.Bytes)
    pssoption := &rsa.PSSOptions{rsa.PSSSaltLengthAuto,crypto.SHA256}
    //使用私钥进行签名
    signature,_ := rsa.SignPSS(rand.Reader,private_key,crypto.SHA256,msg_hash[:],pssoption)

    sendData := make([]byte,len(msg_hash)+len(signature))
    copy(sendData[:len(msg_hash)],msg_hash[:])
    copy(sendData[len(msg_hash):],signature)

    //自此,客户端将sendData通过tcp发送给另一端


    //当另一端接收到数据后 使用公钥来进行验签

    //加载公钥
    //先获取原文
    soureData := sendData[:len(msg_hash)]
    sign := sendData[len(msg_hash):]
    public_block,_ := pem.Decode(PublicKey)
    public_key,_ := x509.ParsePKIXPublicKey(public_block.Bytes)
    pub := public_key.(*rsa.PublicKey)
    err := rsa.VerifyPSS(pub,crypto.SHA256,soureData,sign,nil)
    if err == nil {
        fmt.Println("数据验证通过")
    }
}

备注:x.509证书是为了保证证书的一致性,国际电信联盟设计的一套专门针对证书格式的标准,提供了一种描述证书的格式。X.509数字证书不仅包括用户名和密码,而且还包含了与用户有关的其他信息,通过使用证书,CA可以为证书接收者提供一种方法,使他们不仅信任证书主体的公钥,而且还信任有关证书主体的其他信息

严密的数字加解密,数字签名与验证流程

  • 发送之前,先将发送者的明文进行hash得到消息摘要,再使用发送者的私钥和刚才得到的明文hash进行签名,得到签名;然后将明文,数字签名和数字证书合在一起用发送者随机生成的对称密钥加密得到的密文。接下来,将随机生成的对称密钥使用接收方的公钥进行加密得到数字信封,最后将密文跟数字信封发送给接收者

  • 接收者接收到数据后首先使用私钥解密数字信封得到对称密钥,第二步是使用对称密钥解密密文得到数字签名和证书还有明文hash,最后使用发送者的公钥和数字签名以及明文Hash进行比较,从而验证签名和检验数据的完整性

你可能感兴趣的:(加密算法之RSA与数字签名)