目录
1.1 RSA简介
RSA是一种非对称加密算法,它的名字是由它的三位开发者,即RonRivest、AdiShamir和LeonardAdleman 的姓氏的首字母组成的(Rivest-Shamir-Leonard)。
RSA可以被用于非对称加密和数字签名。
1.2 RSA图解
1.3 RSA加密
- 对代表明文的数字的E次方求modN的结果。就是将明文自己做E次乘法,然后将其结果除以N求余数,这个余数就是密文。
- E和N的组合就是公钥。
- E是加密(Encryption)的首字母,N是数字(Number)的首字母。
- RSA的加密就是 “求E次方的modN"
1.4 RSA解密
- 对表示密文的数字的D次方求modN就可以得到明文。将密文自己做D次乘法,再对其结果除以N求余数,就可以得到明文。
- 数D和数N组合起来就是RSA的解***,因此D和N的组合就是私钥。
- 在RSA中,加密和解密的形式是相同的。加密是求 "E次方的mod N”,而解密则是求 "D次方的modN” 。
- D是解密〈Decryption)的首字母,N是数字(Number)的首字母。
1.5 图解RSA加密解密
1.6 Golang生成公钥和私钥
- 生成私钥流程:
- 使用rsa包中的GenerateKey方法生成私钥
- 通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串
- 将私钥字符串设置到pem格式块中
- 通过pem将设置好的数据进行编码, 并写入磁盘文件中
- 生成公钥流程:
- 从得到的私钥对象中将公钥信息取出
- 通过x509标准将得到 的rsa公钥序列化为字符串
- 将公钥字符串设置到pem格式块中
- 通过pem将设置好的数据进行编码, 并写入磁盘文件
- 示例
/**
*
* !rsa 生成秘钥对函数 GenerateRsaKey 孙东
* @parmas(int)
* @return(nil)
*
*/
func GenerateRsaKey(keySize int) {
//01. 使用rsa中的GenerateKey方法生成私钥
privateKey, err := rsa.GenerateKey(rand.Reader, keySize)
//02. nil
if err != nil {
panic(err)
}
//03. 通过x509标准获取ras私钥序列化为ASN.1的der编码字符串
derText := x509.MarshalPKCS1PrivateKey(privateKey)
//04. 需要组织一个pem.block
block := pem.Block{
Type: "rsa private key", //标题
Bytes: derText,
}
//05. pem编码
file, err := os.Create("private.pem")
if err != nil {
panic(err)
}
//06. pem处理
pem.Encode(file, &block)
//关闭流
file.Close()
//***公钥处理
//01. 从私钥中取出公钥
publickey := privateKey.PublicKey
//02. 使用x509标准序列化
derstream, err2 := x509.MarshalPKIXPublicKey(&publickey)
if err2 != nil {
panic(err)
}
//03. 将的要的数据放到pem.block中
block = pem.Block{
Type: "rsa public key",
Bytes: derstream,
}
//04. pem编码
file, err = os.Create("public.pem")
if err != nil {
panic(err)
}
pem.Encode(file, &block)
//05. 文件关闭
}
- 重要函数:
- GenerateKey函数使用随机数据生成器random生成一对具有指定字位数的RSA**。
"crypto/rsa" 包中的函数 func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err error) - 参数1: io.Reader: 赋值为: rand.Reader -- rand包实现了用于加解密的更安全的随机数生成器。 -- var Reader io.Reader (rand包中的变量) - 参数2: bits: 秘钥长度 - 返回值1: 代表一个RSA私钥。 - 返回值2: 错误信息 - 通过x509 将rsa私钥序列化为ASN.1 PKCS#1 DER编码。
"crypto/x509" 包中的函数 (x509包解析X.509编码的证书和**)。 func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte - 参数1: 通过rsa.GenerateKey得到的私钥 - 返回值: 将私钥通过ASN.1序列化之后得到的私钥编码数据 - 设置Pem编码结构。
Block代表PEM编码的结构。 type Block struct { Type string // 得自前言的类型(如"RSA PRIVATE KEY") Headers map[string]string // 可选的头项,Headers是可为空的多行键值对。 Bytes []byte // 内容解码后的数据,一般是DER编码的ASN.1结构 } - 将得到的Pem格式私钥通过文件指针写入磁盘中。
"encoding/pem" 包中的函数 func Encode(out io.Writer, b *Block) error - 参数1: 可进行写操作的IO对象, 此处需要指定一个文件指针 - 参数2: 初始化完成的Pem块对象, 即Block对象 - 通过RSA私钥得到公钥。
// 私钥 type PrivateKey struct { PublicKey // 公钥 D *big.Int // 私有的指数 Primes []*big.Int // N的素因子,至少有两个 // 包含预先计算好的值,可在某些情况下加速私钥的操作 Precomputed PrecomputedValues } // 公钥 type PublicKey struct { N *big.Int // 模 E int // 公开的指数 } 通过私钥获取公钥 publicKey := privateKey.PublicKey // privateKey为私钥对象 - 通过x509将公钥序列化为PKIX格式DER编码。
"crypto/x509" 包中的函数 func MarshalPKIXPublicKey(pub interface{}) ([]byte, error) - 参数1: 通过私钥对象得到的公钥 - 返回值1:将公钥通过ASN.1序列化之后得到的编码数据 - 返回值2: 错误信息 - 将公钥编码之后的数据格式化为Pem结构, 参考私钥的操作。
- 将得到的Pem格式公钥通过文件指针写入磁盘中。
- 生成的私钥和公钥文件数据。
// 私钥文件数据 -----BEGIN RSA PRIVATE KEY----- MIICXgIBAAKBgQC5bm0DCEV+EFeiLUqSshziqhSB30jXy5BWbPV5SlMq4aWiEknM i+Mw1aXic4bEsM3YyT73eWsifqZNSc/4fRaV4qz5OL8IIe9AZoGDSLX/Ar9AQMJf OHbAtdIlCGQ4d80KjpDpPs2wZkTqllWCg31d7U3DVEm5kqTGtSYIu9e7JQIDAQAB AoGARGdn72ZtvENrEHiEufjajwMO7Zng1TpS1I79PvEcHQWAhHkaoEo6VRl7SD41 yPkv9njGsaQo0WDHGFvSTGhYm/EWGrBWRPc5xXbSBg7ty9Iza9B1ekAj8VfWryen Wje3xDOCVCDUiCcYdaSfPiJPYuWMSnNMNa+0cR921zBQg0ECQQDpCMljuH7LrpbC NDF5q+LbUWMAE2KLDPX4WmDSdZdIO3mPux3MdwOUEfrcvSBGZNB7gyaEG7goZL8G BqL22MJHAkEAy7SqbVPoPbMPHuLI52VQ2FDp6xxSWLhjmv1ePCHGo28MDCaHeVzZ QaxyuIbnY8A6NHfu/QGwz/eB941IjYNBMwJBAI9XEEl+mr++zIz4fdZRnGE7VqId SmgtuL7jGNtb6YpMyyFV/6ZdLp5N0PkmfEvQh0zyBycLxeNS1Q1n16Xu/tECQQCZ dF42wdDgOfWYFMu31VETw9CTtuApya3vYhMNRXx4Pf1bYeMIf/OCT8CUVbwWHwc5 42d73TwvTorvy9TuFgSVAkEA6F69THlTn5oIP8IWHcHuqS01fIR/vGfEwQ4cFZGR ketfieyeeF8rjn4qzwT/ugwRNjkhfKmoILnIC8UhEEJdjA== -----END RSA PRIVATE KEY-----// 公钥文件数据 -----BEGIN RSA PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5bm0DCEV+EFeiLUqSshziqhSB 30jXy5BWbPV5SlMq4aWiEknMi+Mw1aXic4bEsM3YyT73eWsifqZNSc/4fRaV4qz5 OL8IIe9AZoGDSLX/Ar9AQMJfOHbAtdIlCGQ4d80KjpDpPs2wZkTqllWCg31d7U3D VEm5kqTGtSYIu9e7JQIDAQAB -----END RSA PUBLIC KEY-----
1.7 Golang使用RSA
- 公钥加密流程
- 将公钥文件中的公钥读出, 得到使用pem编码的字符串 。
- 将得到的字符串解码 。
- 使用x509将编码之后的公钥解析出来 。
- 使用得到的公钥通过rsa进行数据加密 。
- 私钥解密流程
- 将私钥文件中的私钥读出, 得到使用pem编码的字符串 。
- 将得到的字符串解码 。
- 使用x509将编码之后的私钥解析出来 。
- 使用得到的私钥通过rsa进行数据解密 。
-
公钥加密示例:
/** * * !rsa 公钥加密函数 RsaEncrypt bos2967 * @parmas(text,[]byte) * @return([]byte ) * */ func RsaEncrypt(text string, filename []byte) []byte { //01. 根据文件名将文件内容从文件中读取出来 file, err := os.Open(text) //02. 读文件 if err != nil { panic(err) } //03. 读文件 FileInfo, err2 := file.Stat() //stat函数 返回( fileinfo, err) if err2 != nil { panic(err2) } //04. buffer 对接要读取的数据 buffer := make([]byte, FileInfo.Size()) // n, err3 := file.Read(buffer) if err3 != nil { panic(err3) } defer file.Close() // fmt.Println("--------------------", n) //05. 从数据中查找到下一个pem格式的块 block, _ := pem.Decode(buffer) if block == nil { return nil } //06. 解析一个der编码的公钥 pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return nil } pubKey := pubInterface.(*rsa.PublicKey) //07. 公钥加密 result, _ := rsa.EncryptPKCS1v15(rand.Reader, pubKey, text) //08. 返回加密后的数据 return result }
私钥解密示例:
/**
*
* !rsa 私钥解密函数 RsaDecrypt
* @pma(text,[]byte)
* @return([]byte )
*
*/
func RsaDecrypt(text string, fileName []byte) []byte {
//01. 根据文件名将文件内容从文件中读取出来
file, err := os.Open(text)
//02. 读文件
if err != nil {
panic(err)
}
//03. 读文件
FileInfo, err2 := file.Stat() //stat函数 返回( fileinfo, err)
if err2 != nil {
panic(err2)
}
//04. buffer 对接要读取的数据
buffer := make([]byte, FileInfo.Size())
//
n, err3 := file.Read(buffer)
if err3 != nil {
panic(err3)
}
defer file.Close()
//
fmt.Println("--------------------", n)
//05. 从数据中查找到下一个pem格式的块
block, _ := pem.Decode(buffer)
if block == nil {
return nil
}
//06. 解析一个der编码的私钥
pubInterface, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil
}
//07. 私钥解密
result, _ := rsa.DecryptPKCS1v15(rand.Reader, pubInterface, []byte(text))
//08. 返回私钥后的数据
return result
}
- 重要函数:
- 将得到的Pem格式私钥通过文件指针写入磁盘中
"encoding/pem" 包中的函数 func Decode(data []byte) (p *Block, rest []byte) - 参数 data: 需要解析的数据块 - 返回值1: 从参数中解析出的PEM格式的块 - 返回值2: 参数data剩余的未被解码的数据 - 解析一个DER编码的公钥 , pem中的Block结构体中的数据格式为ASN.1编码
函数所属的包: "crypto/x509" func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error) - 参数 derBytes: 从pem的Block结构体中取的ASN.1编码数据 - 返回值 pub: 接口对象, 实际是公钥数据 - 参数 err: 错误信息 - 解析一个DER编码的私钥 , pem中的Block结构体中的数据格式为ASN.1编码
函数所属的包: "crypto/x509" func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error) - 参数 der: 从pem的Block结构体中取的ASN.1编码数据 - 返回值 key: 解析出的私钥 - 返回值 err: 错误信息 - 将接口转换为公钥
pubKey := pubInterface.(*rsa.PublicKey) - pubInterface: ParsePKIXPublicKey函数返回的 interface{} 对象 - pubInterface.(*rsa.PublicKey): 将pubInterface转换为公钥类型 rsa.PublicKey - 使用公钥加密数据
函数所属的包: "crypto/rsa" func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error) - 参数 rand: 随机数生成器, 赋值为 rand.Reader - 参数 pub: 非对称加密加密使用的公钥 - 参数 msg: 要使用公钥加密的原始数据 - 返回值 out: 加密之后的数据 - 返回值 err: 错误信息 - 使用私钥解密数据
函数所属的包: "crypto/rsa" func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) - 参数 rand: 随机数生成器, 赋值为 rand.Reader - 参数 priv: 非对称加密解密使用的私钥 - 参数 ciphertext: 需要使用私钥解密的数据 - 返回值 out: 解密之后得到的数据 - 返回值 err: 错误信
我想我更懂了.....