非对称加密之RSA(go语言)

1. 简介

在对称密码中,由于加密和解密的密钥是相同的,因此必须向接收者配送密钥。用于解密的密钥必须被配送给
接收者,这一问题称为密钥配送问题。如果使用非对称加密也可以称为公钥密码,则无需向接收者配送用于解
密的密钥,这样就解决了密钥配送问题。可以说非对称加密是密码学历史上最伟大的发明。

非对称加密中,密钥分为加密密钥和解密密钥两种。发送者用加密密钥对消息进行加密,接收者用解密密钥对
密文进行解密。要理解公钥密码,清楚地区分加密密钥和解密密钥是非常重要的。加密密钥是发送者加密时使
用的,而解密密钥则是接收者解密时使用的。

仔细思考一下加密密钥和解密密钥的区别,我们可以发现:

  • 发送者只需要加密密钥
    • 接收者只需要解密密钥
    • 解密密钥不可以被窃听者获取
  • 加密密钥被窃听者获取也没问题

也就是说,解密密钥从一开始就是由接收者自己保管的,因此只要将加密密钥发给发送者就可以解决密钥配送
问题了,而根本不需要配送解密密钥。

RSA是一种非对称加密算法,它的名字是由它的三位开发者,即RonRivest、AdiShamir和LeonardAdleman 的姓氏 的首字母组成的(Rivest-Shamir-Leonard)。

2. RSA加密

在RSA中,明文、密钥和密文都是数字。RSA的 加密过程可以用下列公式来表达,如下。

密文 = 明文^E mod N

也就是说,RSA的密文是对代表明文的数字的E次方求modN的结果。换句话说,就是将明文自己做E次乘法,然 后将其结果除以N求余数,这个余数就是密文。

加密公式中出现的两个数一一一E和N,到底都是什么数呢?RSA的加密是求明文的E次方modN,因此只 要知道E和N这两个数,任何人都可以完成加密的运算。所以说,E和N是RSA加密的密钥,也就是说, E和N的组 合就是公钥 。

不过,E和N并不是随便什么数都可以的,它们是经过严密计算得出的。

有一个很容易引起误解的地方需要大家注意一一E和N这两个数并不是密钥对(公钥和私钥的密钥对)。E和N两 个数才组成了一个公钥,因此我们一般会写成 “公钥是(E,N)” 或者 “公钥是{E, N}" 这样的形式,将E和N用括号 括起来。

3. RSA解密

RSA的解密和加密一样简单,可以用下面的公式来表达

明文 = 密文^D mod N

也就是说,对表示密文的数字的D次方求modN就可以得到明文。换句话说,将密文自己做D次乘法,再对其结果 除以N求余数,就可以得到明文。

这里所使用的数字N和加密时使用的数字N是相同的。 数D和数N组合起来就是RSA的解密密钥,因此D和N的组合 就是私钥 。只有知道D和N两个数的人才能够完成解密的运算。

在RSA中,加密和解密的形式是相同的。加密是求 "E次方的mod N”,而解密则是求 "D次 方的modN” 。

当然,D也并不是随便什么数都可以的,作为解密密钥的D,和数字E有着相当紧密的联系。否则,用E加密的结 果可以用D来解密这样的机制是无法实现的。


RSA加密解密.png

4. Go中生成公钥和私钥

  • 生成私钥操作流程概述:
  1. 使用rsa中的GenerateKey方法生成私钥
  2. 通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串
  3. 将私钥字符串设置到pem格式块中
  4. 通过pem将设置好的数据进行编码, 并写入磁盘文件中
  • 生成公钥操作流程:
  1. 从得到的私钥对象中将公钥信息取出
  2. 通过x509标准将得到 的rsa公钥序列化为字符串
  3. 将公钥字符串设置到pem格式块中
  4. 通过pem将设置好的数据进行编码, 并写入磁盘文件
  • 生成公钥和私钥的源代码:
/*
 * 生成RSA公钥和私钥并保存在对应的目录文件下
 * 参数bits: 指定生成的秘钥的长度, 单位: bit
 */

func RsaGenKey(bits int, privatePath,pubulicPath string) error {
    // 1. 生成私钥文件
    // GenerateKey函数使用随机数据生成器random生成一对具有指定字位数的RSA密钥
    privateKey, err := rsa.GenerateKey(rand.Reader, bits)
    if err != nil {
        return err
    }
    // 2. MarshalPKCS1PrivateKey将rsa私钥序列化为ASN.1 PKCS#1 DER编码
    derPrivateStream := x509.MarshalPKCS1PrivateKey(privateKey)

    // 3. Block代表PEM编码的结构, 对其进行设置
    block := pem.Block{
        Type:  "RSA PRIVATE KEY",
        Bytes: derPrivateStream,
    }

    // 4. 创建文件
    privateFile, err := os.Create(privatePath)
    defer privateFile.Close()

    if err != nil {
        return err
    }

    // 5. 使用pem编码, 并将数据写入文件中
    err = pem.Encode(privateFile, &block)
    if err != nil {
        return err
    }

    // 1. 生成公钥文件
    publicKey := privateKey.PublicKey
    derPublicStream, err := x509.MarshalPKIXPublicKey(&publicKey)
    if err != nil {
        return err
    }

    block = pem.Block{
        Type:  "RSA PUBLIC KEY",
        Bytes: derPublicStream,
    }

    publicFile, err := os.Create(pubulicPath)
    defer publicFile.Close()

    if err != nil {
        return err
    }

    // 2. 编码公钥, 写入文件
    err = pem.Encode(publicFile, &block)
    if err != nil {
        panic(err)
        return err
    }
    return nil
}

测试代码:

func testGenRSA()  {
    rsa.RsaGenKey(2048, "privateKey.pem","pubulicKey.pem")
}

5. Go中使用RSA

5.1. 操作步骤

  • 公钥加密
  1. 将公钥文件中的公钥读出, 得到使用pem编码的字符串
  2. 将得到的字符串解码
  3. 使用x509将编码之后的公钥解析出来
  4. 使用得到的公钥通过rsa进行数据加密
  • 公钥解密
  1. 将私钥文件中的私钥读出, 得到使用pem编码的字符串
  2. 将得到的字符串解码
  3. 使用x509将编码之后的私钥解析出来
  4. 使用得到的私钥通过rsa进行数据解密

5.2. 代码实现

  • RSA公钥加密
/*
 * RSA公钥加密
 */
func RSAEncrypt(src []byte, filename string) ([]byte, error)  {
    // 根据文件名读出文件内容
    file, err := os.Open(filename)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    info, _ := file.Stat()
    buf := make([]byte, info.Size())
    file.Read(buf)

    // 从数据中找出pem格式的块
    block, _ := pem.Decode(buf)
    if block == nil {
        return nil, err
    }

    // 解析一个der编码的公钥
    publicKey, err := x509.ParsePKCS1PublicKey(block.Bytes)
    if err != nil {
        return nil, err
    }

    // 公钥加密
    result, _ := rsa.EncryptPKCS1v15(rand.Reader, publicKey, src)
    return result, nil

}
  • RSA私钥解密
/*
 * RSA私钥解密
 */
func RSADecrypt(src []byte, filename string) ([]byte, error) {
    // 根据文件名读出内容
    file, err := os.Open(filename)
    if err != nil {
        return nil,err
    }
    defer file.Close()

    info, _ := file.Stat()
    buf := make([]byte, info.Size())
    file.Read(buf)

    // 从数据中解析出pem块
    block, _ := pem.Decode(buf)
    if block == nil {
        return nil,err
    }

    // 解析出一个der编码的私钥
    privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)


    // 私钥解密
    result, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, src)
    if err != nil {
        return nil,err
    }
    return result,nil
}
  • 测试代码:
func testRSA()  {
    msg := "二愣子抗日"
    cipherText, _:= rsa.RSAEncrypt([]byte(msg), "publicKey.pem")
    fmt.Println(string(cipherText))

    plainText, _:= rsa.RSADecrypt(cipherText, "privateKey.pem")
    fmt.Println(string(plainText))
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,607评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,239评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,960评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,750评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,764评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,604评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,347评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,253评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,702评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,893评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,015评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,734评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,352评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,934评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,052评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,216评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,969评论 2 355