From 6ff8d34df1dab5dc8f44e75a588204b5b0a83aed Mon Sep 17 00:00:00 2001 From: TRHX Date: Tue, 12 Mar 2024 00:58:16 +0800 Subject: [PATCH] add: rsa algorithm --- .../07.rsa.md" | 239 +++++++++++++++++- 1 file changed, 235 insertions(+), 4 deletions(-) diff --git "a/docs/03.\350\276\205\345\212\251\346\237\245\350\257\242/04.\345\212\240\345\257\206\347\256\227\346\263\225/07.rsa.md" "b/docs/03.\350\276\205\345\212\251\346\237\245\350\257\242/04.\345\212\240\345\257\206\347\256\227\346\263\225/07.rsa.md" index 1d0f9d10..6e754d17 100644 --- "a/docs/03.\350\276\205\345\212\251\346\237\245\350\257\242/04.\345\212\240\345\257\206\347\256\227\346\263\225/07.rsa.md" +++ "b/docs/03.\350\276\205\345\212\251\346\237\245\350\257\242/04.\345\212\240\345\257\206\347\256\227\346\263\225/07.rsa.md" @@ -74,7 +74,7 @@ RSA 密钥的模数是公钥和私钥中的一个重要参数,通常用大素 - 公钥使用 `spki` 标准,得到的公钥以 `-----BEGIN PUBLIC KEY-----` 开头; - 私钥使用 `pkcs1` 标准,得到的私钥以 `-----BEGIN RSA PRIVATE KEY-----` 开头; - 私钥使用 `pkcs8` 标准,得到的私钥以 `-----BEGIN PRIVATE KEY-----` 开头。 -- 私钥使用 `pkcs1` 标准,如果对私钥进行了加密,则得到的私钥包含 `Proc-Type`、`DEK-Info` 字段; +- 私钥使用 `pkcs1` 标准,如果对私钥进行了加密,则得到的私钥以 `-----BEGIN RSA PRIVATE KEY-----` 开头,但内容里包含 `Proc-Type`、`DEK-Info` 字段; - 私钥使用 `pkcs8` 标准,如果对私钥进行了加密,则得到的私钥以 `-----BEGIN ENCRYPTED PRIVATE KEY-----` 开头。 --- @@ -104,6 +104,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we ::: ### Python +
@@ -324,6 +325,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we ### JavaScript +
@@ -499,16 +501,237 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we ### Golang +```go +// ✅ 无需安装依赖,官方文档:https://pkg.go.dev/crypto +// ❌ 公钥指数不支持自定义,默认 65537(0x10001),该值是除了 1、3、5、17、257 之外的最小素数 +// ❌ 密钥输出格式不支持 jwk、openssh +// ❌ 对私钥进行签名、加密,只支持 pkcs1 标准的私钥,不支持 pkcs8 标准的私钥 + +package main + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "fmt" +) + +func main() { + rsaKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + fmt.Println("Generate key failed:", err) + return + } + + // 私钥输出格式 der,私钥语法标准支持 pkcs1 (MarshalPKCS1PrivateKey)、pkcs8 (MarshalPKCS8PrivateKey) + privateKeyDER := x509.MarshalPKCS1PrivateKey(rsaKey) + + // 可选操作:使用密码加密私钥,注意,EncryptPEMBlock 方法正在被弃用,该方法只能加密 pkcs1 标准的私钥 + // blockType 参数指定密钥的标头,与私钥语法标准对应:pkcs1 加密对应 "RSA PRIVATE KEY" + // alg 参数指定加密算法,参见:https://pkg.go.dev/crypto/x509#PEMCipher + password := []byte("spiderapi") + encryptedPrivateKeyPEMBlock, err := x509.EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", privateKeyDER, password, x509.PEMCipherAES256) + if err != nil { + fmt.Println("Private key encrypt failed:", err) + return + } + encryptedPrivateKeyPEM := pem.EncodeToMemory(encryptedPrivateKeyPEMBlock) + + // 将私钥转为 pem 格式 + // Type 参数指定密钥的标头,与私钥语法标准对应:pkcs1 对应 "RSA PRIVATE KEY",pkcs8 对应 "PRIVATE KEY" + privateKeyPEM := pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: privateKeyDER, + }) + + // 公钥输出格式 der,公钥语法标准支持 pkcs1 (MarshalPKCS1PublicKey)、spki (MarshalPKIXPublicKey) + publicKeyPEM, err := x509.MarshalPKIXPublicKey(&rsaKey.PublicKey) + if err != nil { + fmt.Println("Public Key encoding failed:", err) + return + } + + // 将公钥转为 pem 格式 + // Type 参数指定密钥的标头,与公钥语法标准对应:pkcs1 对应 "RSA PUBLIC KEY",spki 对应 "PUBLIC KEY" + publicKey := pem.EncodeToMemory(&pem.Block{ + Type: "PUBLIC KEY", + Bytes: publicKeyPEM, + }) + + fmt.Println("RSA 公钥(spki、pem):\n\n", string(publicKey)) + fmt.Println("RSA 私钥(pkcs1、pem):\n\n", string(privateKeyPEM)) + fmt.Println("RSA 加密后的私钥(pkcs1、pem、aes-256-cbc):\n\n", string(encryptedPrivateKeyPEM)) +} + +/* +RSA 公钥(spki、pem): + +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1P94ik8uUca0kq613hw0 +dy0i/dALloDg4I32lkk7eWV/obe2I/qEY2Nz7SmmY8VZeJUfiQuAVuOxFYI7rKPM +4LvSvkKC5xcWho1319eyZKC1AYlXKHjQPrUXNrDwmM1racGw9NopFg/GyikhaZiT +vsW7NM3O3HN26irQXFO0C7vypIaZtOIB9YVA9YFpBLNnINczRyekltoZqhL4j/Of +C+VuXZOxL0wfJOML7axF4Fwt7XSir8BPJMoEc2KVFYxMMd06tfJMRzvHOEckOaob +ZLrZjHM4YzDr32ClpgCazx7QWsBiMo3AqMuNO+LBV/VynsZPymgehIiDRGr7+S0F +ywIDAQAB +-----END PUBLIC KEY----- + +RSA 私钥(pkcs1、pem): + +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA1P94ik8uUca0kq613hw0dy0i/dALloDg4I32lkk7eWV/obe2 +I/qEY2Nz7SmmY8VZeJUfiQuAVuOxFYI7rKPM4LvSvkKC5xcWho1319eyZKC1AYlX +KHjQPrUXNrDwmM1racGw9NopFg/GyikhaZiTvsW7NM3O3HN26irQXFO0C7vypIaZ +tOIB9YVA9YFpBLNnINczRyekltoZqhL4j/OfC+VuXZOxL0wfJOML7axF4Fwt7XSi +r8BPJMoEc2KVFYxMMd06tfJMRzvHOEckOaobZLrZjHM4YzDr32ClpgCazx7QWsBi +Mo3AqMuNO+LBV/VynsZPymgehIiDRGr7+S0FywIDAQABAoIBAQDSQhYFwkAhLZvX +KGwTg5gvBPmDv7mQqkxSnxEKLeRt48noI+fDAGtriSNIvFKqLogxxlNI/3eDTmTi +rJqnw1Jdjkts0U9TO7FaxY/GHADX4OSNTbwiEZDQNgdiT6xRyoX78d3y9uCUDKLZ +sVxwVtOSALLaX0eSytBaPEVOvrn+0Y06x/jiKhHvw1LCNc+E0lp3myrwW+6f0LCJ +KD4dc5AWop64psKwDXP2t8bcyK5uhLjZYiSKjSi+7y8kCNmN0LimYjbjt8nvHo1J +s24BbfE/MwrXhuV2/1ODBezPoOLBm51rzt9syHHnQBh95LPdLPr5N5r5uPvkToDu +X5eM5ughAoGBAPxvHiyoKjWTc2cYw2exsabp2OOkKHH5BP8VBErEvTzmbzr9mKFR +PG0ZcxLnSPux9xaoExdNd+NPnVWl5sR3ZLezGLSaeZw5RagTlkQ/YOXZ6b7mWZcE +hpZNlvSyG3dIP63N4ONwTCpRrjyndv/sSGARrHsp4I1mv+23cQaQfvADAoGBANgB +vUh8Uekq6SuJ2MmvX63cq5kK6BejWfEk6xFlHOTE49yzorn8yJoy1dBoO5BN1VcZ +NUPSNt7PP0HR0BAgX5pKun/dAIs9+Y4HJPojeLkkhFgjx0FxQrQ2usIAaqAwZlpC +rzClr7/8ZO5jeZMdfxcqE43KNrWOWGleyYQnr9yZAoGAcMPCmvhUQrKnrrplMAE0 +9vcnqClA2AkBrmFZFX1le7sEnTmD4SxE7gecXCltdOI/GqPiQ1qb37NE+Wmu+LzN +BTLAKo2HHb6H21lEmyAkzQjXXivQgaHH7YSjlpOpqVNg/uclOvSDUbRDPV0hz5lh +i2jZv/spEIGB41M67k/GJLkCgYAzRZZsUjYPJoRaNUoj9WC8oBiLJy+YDMoYly7E +3j9RffqoNGt3wizLjS17XoJk6lSta+pcwtULZh4ZvXepnEWVFg/WsdqjMn6926xH +Q4wwRh6z3So6umue4y7JRdgJVfO1kQaMgYeKBpreivYcmW/FS9OAYHND/Rm3SSyE +FfeEYQKBgAVICBeE9LrMzoPwaTiGcRwEbx13Mo2SgzrKiwSY960Ewlu5t17197e0 +EEqJ1Y+ItIA+4j9XEMu6e1hV56Zy9rNEOyUZSB83tB1TQTzasbTDLfh0vJZmbudF +6VTo4nST7kLzJYJe4A1SF2gLKasrbBL0Ye22PK2AuwHIWca2e+OS +-----END RSA PRIVATE KEY----- + +RSA 加密后的私钥(pkcs1、pem、aes-256-cbc): + +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,3a42d48c94f2f06b0354a04de8247917 + +6rr+ZAQXJXS3zv9gZUbSp+Ft1ngcjshRrlKYcbeXaBPbWwfwE0iwG47aSJIpAvR1 +ac2NhCTyq8ATqbjrhdf4dSHGYwpLJZzdQ7X+g3FmvJpLJMglaLhM2ls+IN+ofOS+ +Bp9DwCSvdvTQEocHqTImXS98Bb6pr49FdJmQMma8pm2U73fIro8apVTDwQD/iHIB +nEQ6+ZvUIqp+spEifYle0d1q1ADU/ZavqMt21bDhz56Ccf++6unXk+BhYVGj1WX0 +LYmZS8yRVHWDPk19i8yOCeMfZSS929JhCIsRVWYomxSVdwQP6h2iG4tU2+5mvDo1 +Pbr4BrLKjFCO3ixhbjmW+ySNoNB/dNkkNd4eaBvmUoC1A/sNz3rJQR2Kl5r9kOCi +iVzh7hpPHTGmW9GY3PBYsIIE84HwrMpmcHHX/qWg/P5B/qAqOXQb4n8UozwuICdn +w/i8c/k6YwOndYkIUqJjUg4KmWTdAQkyaCceBi/i4p9XgWZvq7MKQSQw0K9SeBoz +Q7zUmJjFBtaLN/N3ckyuTeWQOZtGlVjK/rZKFy99RsMum//HX+S8XciUgs2p8A0f +HMrIpgFg3XQSW5el4ykNdS216hEmMtUWfrGhn5D4UEDIHMRF5j9abR2T2BhKbh8m +KcagOdBRRdKBH8JU8l3NT+tSYI+DpbMFH7X1QwfZNVlChAZblipOT9PpW4LbuZhv +nIDU7KjodaV1JrRSOs/+9ferPKxkCXsGj3n5W/9wfbwUnChhhuYXvBVbNd48Os9m +j5jQFVdcxQNe4UyYa7L3KaEzbp9GwX6MsUbiATH7jqEqfero50oTEznWKh4GQtrZ +UL5QhESMEb+3X+JC1nu3aFzbvm+Y0dRjj5bi/R4wk1CAMIOWyT/iYSz+Oe9CNsVA +gKQ5pjY4fwrLjwXVDsm52sQT99V6fVWbUXmg1iNrZ3hbLZ7sGZ0iK6ecz+x4zzMG +m7/7Lbdb0wwGD+K5RPtDmmR9PvwCbxdfQGy8sLyUnUIB1btLRyTnPTXseuIZyFLu +BKWTeLWhqya2h7B9iDYxQq1ySKAJaD8n6Rp+plUqJiyaO/RYcJRwun/U/GVuSfct +YT1BytgfGqM6GL0S+RzFuaG7EYgg8vRuKwHw9rjdaIIz//cL/Y8YCJhJIhmVd7GJ +NE5f+DXPvhhMf/12CF/rcGy6VVGnhlCHN+6dHWeodcbQVbuMJaznasqTk8NuWV75 +fZ70FmdHlJHHzTmZ/bQe6qp/1IKLYxa5v8lZEG9ER2hQ2uSjOzLt0nRc8K/HX7xA +Fi+8mRxjsOok75QKfJHNyCXL33hxDclnGbqANUp8bE45h1F3RWnQ60QYc6/EVE9Y +FOKqqOMrTjcIebJN4zYNUDT1OClB6VdyaJLmPtzIYDE07qwWoHdGWVQmrofR/hzL +5+c3LY2AtxQvIyWJc7BmP6lp46KmoUcc9BLkydi5bp9XDM2OgZGjHN9pkdhqdyNH +3zkUzf5dimvaPLHHlKtz1MNF7LTkPRJX94ATq1PDhsgX9OX0lvI10lb+MCI483Mq +IOIIMVT9256lXj+b+q+AhxkhSg4vMLmv28/O8+QZehwcqM1CeA4qzafLGziA/6tl +-----END RSA PRIVATE KEY----- +*/ +``` + +## 解析密钥 +### Python +
+ - + - + -## 解析密钥 +### JavaScript +
+ + + + ```javascript + // ✅ 安装依赖:npm install node-forge,官方文档:https://github.com/digitalbazaar/forge + + var forge = require("node-forge"); + + var publicKeyPEM = ` + -----BEGIN PUBLIC KEY----- + MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCl7HWuXcOH9I/Bud7dplYxHOEC + D82fJv1WJKADhmILCxDLJLVkueBQfwUItPELF3RLhs+3+XNYfGiz7PPPhxV1pey5 + jrHT8zw8InrNRwlDeCyx/Q+ETpSpQImvILf0RBHtnOgVpb41uhKF24wGH4q7+faN + w6cBVKhFn+fuItSGfQIDAQAB + -----END PUBLIC KEY----- + ` + + var privateKeyPEM = ` + -----BEGIN RSA PRIVATE KEY----- + MIICXgIBAAKBgQCl7HWuXcOH9I/Bud7dplYxHOECD82fJv1WJKADhmILCxDLJLVk + ueBQfwUItPELF3RLhs+3+XNYfGiz7PPPhxV1pey5jrHT8zw8InrNRwlDeCyx/Q+E + TpSpQImvILf0RBHtnOgVpb41uhKF24wGH4q7+faNw6cBVKhFn+fuItSGfQIDAQAB + AoGBAKSmc1kmfoQJciZh1gDJsTpnV/l9ySQnwrma+pbE4cHnpzCPKtnbgfcfNNWh + CJljGupfyvzbs1SZkCUL/B1yBR3uAbWw5G0uzJo61wYciufnQA1/lu3JyEyLeSxb + eFOIkuI8Ce0SCPT01+6sR77EA0VtUA+0Ak7OI4EvElFPn0qBAkEA8SvKXG6suLFL + 9TjUH2B1XDwMxQFw7JOOhAyLcbNJMLgqMhHuqvTW/T4oxTQh7LbDMP977ZDnkmdt + L8S7zAHHsQJBALAgOFkbNNH4FzBQtxyWEu6+D0ZhvhIAIoH0pDBdoIO9vKalRgWy + vV6YsI3NujjBjz1p7g3Zb/zliA3vH9ieqo0CQQCdlOVmvBIzo/Vjx7wivF4y5DHb + z/M/QbMPaTr8Eg+yu8MmcD0oi06mriTppgS8rTahH26UbehB6z6Wxc+Hn2ohAkEA + r2GmOrToyBzvmmEFtiWK/MmtlDxIdMxFkHr39GGHMSiC7r6tF4eBIu2RAePWiCXW + aSVOs+PNrFs0PAvd/mshEQJAYpxilxZI7hJT89Qne6CgPXqqZf0sFX0FeR9AJaj1 + g2c+B9GgZ+Nou4ne4WXjOVUWZuuch7yqn3XoxeQT4/xaCw== + -----END RSA PRIVATE KEY----- + ` + + // 解码 PEM 格式的公钥和密钥 + var publicKey = forge.pki.publicKeyFromPem(publicKeyPEM); + var privateKey = forge.pki.privateKeyFromPem(privateKeyPEM); + + // 获取模数(modulus),使用 16 进制字符串表示,从公钥和私钥中均可获取,且值是一样的 + var modulus = publicKey.n.toString(16); // 或者 privateKey.n.toString(16); + + // 计算密钥的位数,即模数(modulus)的位数,16 进制转换为位数时每个字符代表 4 位 + var keyLength = modulus.length * 4; + + // 获取公钥指数 + var publicExponent = publicKey.e.toString(); + + // 获取私钥指数 + var privateExponent = privateKey.d.toString(16); + + console.log("模数为: ", modulus); // a5ec75ae5dc387f48fc1b9dedda656311ce1020fcd9f26fd5624a00386620b0b10cb24b564b9e0507f0508b4f10b17744b86cfb7f973587c68b3ecf3cf871575a5ecb98eb1d3f33c3c227acd470943782cb1fd0f844e94a94089af20b7f44411ed9ce815a5be35ba1285db8c061f8abbf9f68dc3a70154a8459fe7ee22d4867d + console.log("密钥(模数)位数为: ", keyLength); // 1024 + console.log("公钥指数为: ", publicExponent); // 65537 (0x10001) + console.log("私钥指数为: ", privateExponent); // a4a67359267e8409722661d600c9b13a6757f97dc92427c2b99afa96c4e1c1e7a7308f2ad9db81f71f34d5a10899631aea5fcafcdbb3549990250bfc1d72051dee01b5b0e46d2ecc9a3ad7061c8ae7e7400d7f96edc9c84c8b792c5b78538892e23c09ed1208f4f4d7eeac47bec403456d500fb4024ece23812f12514f9f4a81 + ``` + + + + + + +### Golang +
+ + + + + + + + + +## 转换密钥 ### Python +
@@ -519,6 +742,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we ### JavaScript +
@@ -529,6 +753,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we ### Golang +
@@ -540,6 +765,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we ## 加密/解密 ### Python +
@@ -550,6 +776,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we ### JavaScript +
@@ -560,6 +787,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we ### Golang +
@@ -571,6 +799,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we ## 签名/验签 ### Python +
@@ -581,6 +810,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we ### JavaScript +
@@ -588,6 +818,7 @@ PKCS#1、PKCS#5、PKCS#7、PKCS#8 到底是什么?:[https://blog.csdn.net/we ### Golang +