├── .gitignore ├── LICENSE ├── README.md ├── go.mod ├── go.sum ├── main.go ├── pfx └── pfx.go ├── rsa ├── cer.go └── rsa.go └── sha1withrsa └── sha1withrsa.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | .idea/ 17 | .other/ 18 | cert/ 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## go-rsa 2 | 3 | ### 安装 4 | 5 | ```bash 6 | go get github.com/melf-xyzh/go-rsa 7 | ``` 8 | 9 | ### 使用方法 10 | 11 | ### sha1withrsa 12 | 13 | ##### 签名 14 | 15 | ```go 16 | // 需要签名的文本 17 | context := "helloworld" 18 | // 签名 19 | sign, err := sha1withrsa.Sign(privateKey, context) 20 | if err != nil { 21 | log.Fatalln(err) 22 | } 23 | fmt.Println(sign) 24 | ``` 25 | 26 | ##### 验签 27 | 28 | ```go 29 | // 验签 30 | verify, err := sha1withrsa.RSAVerify(publicKey, context, sign) 31 | if err != nil { 32 | return 33 | } 34 | fmt.Println(verify) 35 | ``` 36 | 37 | ### 加密 / 解密 38 | 39 | ```go 40 | // 加密 41 | encrypt, err := myrsa.RsaEncrypt(publicKey, content) 42 | if err != nil { 43 | return 44 | } 45 | // 解密 46 | data, err := myrsa.RsaDecrypt(privateKey,encrypt) 47 | if err != nil { 48 | return 49 | } 50 | ``` 51 | 52 | ### 生成读取公私钥文件(pem格式 / PKCS1) 53 | 54 | ```go 55 | // 生成公钥文件(pem格式) 56 | err = myrsa.CreatePrivatePem(privateKey, "") 57 | if err != nil { 58 | log.Fatal(err) 59 | } 60 | // 读取私钥文件(pem格式) 61 | err = myrsa.CreatePublicPem(publicKey, "") 62 | if err != nil { 63 | log.Fatal(err) 64 | } 65 | // 读取私钥文件(pem格式) 66 | privateKey, err = myrsa.ReadPrivatePem("cert/private.pem") 67 | if err != nil { 68 | log.Fatal(err) 69 | } 70 | // 读取公钥文件(pem格式) 71 | publicKey, err = myrsa.ReadPublicPem("cert/public.pem") 72 | if err != nil { 73 | log.Fatal(err) 74 | } 75 | ``` 76 | 77 | ### 生成读取公私钥文件(ec格式 / PKCS8) 78 | 79 | ```go 80 | // 生成私钥文件(ec格式) 81 | err = myrsa.CreatePrivateEC(privateKey, "cert/private.key") 82 | if err != nil { 83 | log.Fatal(err) 84 | } 85 | // 生成公钥文件(ec格式) 86 | err = myrsa.CreatePublicEC(publicKey, "cert/public.key") 87 | if err != nil { 88 | log.Fatal(err) 89 | } 90 | // 读取私钥文件(ec格式) 91 | privateKey, err = myrsa.ReadPrivateEC("cert/private.key") 92 | if err != nil { 93 | log.Fatal(err) 94 | } 95 | // 读取公钥文件(ec格式) 96 | publicKey, err = myrsa.ReadPublicEC("cert/public.key") 97 | if err != nil { 98 | log.Fatal(err) 99 | } 100 | ``` 101 | 102 | ### 生成证书文件(CA) 103 | 104 | ```go 105 | // 生成CA证书 106 | err = myrsa.CreateCertificate(publicKey, privateKey, "cert/ca/") 107 | if err != nil { 108 | log.Fatal(err) 109 | } 110 | // 导入CA证书 111 | certificate, err := myrsa.LoadCertificate("cert/ca/ca.crt") 112 | if err != nil { 113 | log.Fatal(err) 114 | } 115 | ``` 116 | 117 | ### PFX证书 118 | 119 | ```go 120 | // 从PFX证书中解析公私钥 121 | privateKey, publicKey, err := pfx.GetPublicAndPrivateKeyFromPfx("zhengshu.pfx", "123456") 122 | if err != nil { 123 | return 124 | } 125 | pfx.PrintPublicKey(publicKey) 126 | pfx.PrintPrivateKey(privateKey) 127 | ``` 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/melf-xyzh/go-rsa 2 | 3 | go 1.17 4 | 5 | require golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e 6 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= 2 | golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 3 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 4 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 5 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 6 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 7 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 8 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 9 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 10 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @Time :2022/6/7 12:38 3 | * @Author :Xiaoyu.Zhang 4 | */ 5 | 6 | package main 7 | 8 | import ( 9 | "crypto/rsa" 10 | "fmt" 11 | "github.com/melf-xyzh/go-rsa/pfx" 12 | "github.com/melf-xyzh/go-rsa/rsa" 13 | "github.com/melf-xyzh/go-rsa/sha1withrsa" 14 | "log" 15 | ) 16 | 17 | func main() { 18 | content := "123456789" 19 | 20 | // 生成公钥和私钥 21 | privateKey, publicKey, err := myrsa.GenerateRsaKey(512) 22 | if err != nil { 23 | return 24 | } 25 | 26 | //myrsa.CreateZhenShu(publicKey, privateKey) 27 | sign, err := sha1withrsa.Sign(privateKey, content) 28 | if err != nil { 29 | log.Fatal(err) 30 | } 31 | fmt.Println(sign) 32 | verify, err := sha1withrsa.RSAVerify(publicKey, content, sign) 33 | if err != nil { 34 | log.Fatal(err) 35 | } 36 | fmt.Println(verify) 37 | 38 | // 生成公钥文件(pem格式) 39 | err = myrsa.CreatePrivatePem(privateKey, "") 40 | if err != nil { 41 | log.Fatal(err) 42 | } 43 | // 读取私钥文件(pem格式) 44 | err = myrsa.CreatePublicPem(publicKey, "") 45 | if err != nil { 46 | log.Fatal(err) 47 | } 48 | 49 | privateKey, err = myrsa.ReadPrivatePem("cert/private.pem") 50 | if err != nil { 51 | log.Fatal(err) 52 | } 53 | 54 | publicKey, err = myrsa.ReadPublicPem("cert/public.pem") 55 | if err != nil { 56 | log.Fatal(err) 57 | } 58 | 59 | sign, err = sha1withrsa.Sign(privateKey, content) 60 | if err != nil { 61 | log.Fatal(err) 62 | } 63 | fmt.Println(sign) 64 | verify, err = sha1withrsa.RSAVerify(publicKey, content, sign) 65 | if err != nil { 66 | log.Fatal(err) 67 | } 68 | fmt.Println(verify) 69 | 70 | // 生成私钥文件(ec格式) 71 | err = myrsa.CreatePrivateEC(privateKey, "cert/private.key") 72 | if err != nil { 73 | log.Fatal(err) 74 | } 75 | // 生成公钥文件(ec格式) 76 | err = myrsa.CreatePublicEC(publicKey, "cert/public.key") 77 | if err != nil { 78 | log.Fatal(err) 79 | } 80 | 81 | privateKey, err = myrsa.ReadPrivateEC("cert/private.key") 82 | if err != nil { 83 | log.Fatal(err) 84 | } 85 | 86 | publicKey, err = myrsa.ReadPublicEC("cert/public.key") 87 | if err != nil { 88 | log.Fatal(err) 89 | } 90 | 91 | sign, err = sha1withrsa.Sign(privateKey, content) 92 | if err != nil { 93 | log.Fatal(err) 94 | } 95 | fmt.Println(sign) 96 | verify, err = sha1withrsa.RSAVerify(publicKey, content, sign) 97 | if err != nil { 98 | log.Fatal(err) 99 | } 100 | fmt.Println(verify) 101 | 102 | err = myrsa.CreateCertificate(publicKey, privateKey, "cert/ca/") 103 | if err != nil { 104 | log.Fatal(err) 105 | } 106 | 107 | certificate, err := myrsa.LoadCertificate("cert/ca/ca.crt") 108 | if err != nil { 109 | log.Fatal(err) 110 | } 111 | pfx.GetPublicKeyString(publicKey) 112 | publicKey = certificate.PublicKey.(*rsa.PublicKey) 113 | pfx.GetPublicKeyString(publicKey) 114 | 115 | // 加密 116 | encrypt, err := myrsa.RsaEncrypt(publicKey, content) 117 | if err != nil { 118 | return 119 | } 120 | fmt.Println(encrypt) 121 | // 解密 122 | data, err := myrsa.RsaDecrypt(privateKey, encrypt) 123 | if err != nil { 124 | return 125 | } 126 | fmt.Println(data) 127 | } 128 | -------------------------------------------------------------------------------- /pfx/pfx.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @Time :2022/6/6 14:42 3 | * @Author :Xiaoyu.Zhang 4 | */ 5 | 6 | package pfx 7 | 8 | import ( 9 | "crypto/rsa" 10 | "crypto/x509" 11 | "encoding/base64" 12 | "errors" 13 | "golang.org/x/crypto/pkcs12" 14 | "io/ioutil" 15 | "os" 16 | ) 17 | 18 | //参考文档: 19 | //https://studygolang.com/articles/29971?fr=sidebar 20 | //https://www.csdn.net/tags/MtTaEgzsMDg0MDA0LWJsb2cO0O0O.html 21 | 22 | // GetPublicAndPrivateKeyFromPfx 23 | /** 24 | * @Description: 从PFX证书中解析公私钥 25 | * @param pfxPath PFX证书 26 | * @param privatePassword 密码 27 | * @return privateKey 私钥 28 | * @return publicKey 公钥 29 | * @return err 错误 30 | */ 31 | func GetPublicAndPrivateKeyFromPfx(pfxPath, privatePassword string) (privateKey *rsa.PrivateKey, publicKey *rsa.PublicKey, err error) { 32 | // 打开文件 33 | f, err := os.Open(pfxPath) 34 | defer f.Close() 35 | if err != nil { 36 | return 37 | } 38 | // 读取文件 39 | bytes, err := ioutil.ReadAll(f) 40 | if err != nil { 41 | return 42 | } 43 | // 因为pfx证书公钥和密钥是成对的,所以要先转成pem.Block 44 | blocks, err := pkcs12.ToPEM(bytes, privatePassword) 45 | if err != nil { 46 | return 47 | } 48 | if len(blocks) != 2 { 49 | err = errors.New("解密错误") 50 | return 51 | } 52 | // 拿到第一个block,用x509解析出私钥(当然公钥也是可以的) 53 | privateKey, err = x509.ParsePKCS1PrivateKey(blocks[0].Bytes) 54 | if err != nil { 55 | return 56 | } 57 | // 解析公钥 58 | x509Cert, err := x509.ParseCertificate(blocks[1].Bytes) 59 | if err != nil { 60 | return 61 | } 62 | publicKey = x509Cert.PublicKey.(*rsa.PublicKey) 63 | return 64 | } 65 | 66 | // GetPublicKeyString 67 | /** 68 | * @Description: 获取Base64编码的公钥 69 | * @param publicKey 70 | * @return publicKeyString 71 | */ 72 | func GetPublicKeyString(publicKey *rsa.PublicKey) (publicKeyString string) { 73 | publicKeyByte := x509.MarshalPKCS1PublicKey(publicKey) 74 | publicKeyString = base64.StdEncoding.EncodeToString(publicKeyByte) 75 | return 76 | } 77 | 78 | // GetPrivateKeyString 79 | /** 80 | * @Description: 获取Base64编码的私钥 81 | * @param privateKey 82 | * @return privateKeyString 83 | */ 84 | func GetPrivateKeyString(privateKey *rsa.PrivateKey) (privateKeyString string) { 85 | privateKeyByte := x509.MarshalPKCS1PrivateKey(privateKey) 86 | privateKeyString = base64.StdEncoding.EncodeToString(privateKeyByte) 87 | return 88 | } 89 | -------------------------------------------------------------------------------- /rsa/cer.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @Time :2022/6/7 15:33 3 | * @Author :Xiaoyu.Zhang 4 | */ 5 | 6 | package myrsa 7 | 8 | import ( 9 | "crypto/rand" 10 | "crypto/rsa" 11 | "crypto/x509" 12 | "crypto/x509/pkix" 13 | "encoding/pem" 14 | "errors" 15 | "math/big" 16 | "os" 17 | "path" 18 | "path/filepath" 19 | "time" 20 | ) 21 | 22 | // 参考文档:https://blog.csdn.net/weixin_38299404/article/details/117341068 23 | // 参考文档:https://blog.csdn.net/youngZ_H/article/details/123625301 24 | 25 | // CreateCertificate 26 | /** 27 | * @Description: 生成自签证书文件(RSA) 28 | * @param publicKey 公钥 29 | * @param privateKey 私钥 30 | * @param path 证书保存路径(不包含证书名) 31 | * @return err 错误 32 | */ 33 | func CreateCertificate(publicKey *rsa.PublicKey, privateKey *rsa.PrivateKey, caPath string) (err error) { 34 | // 创建证书模板 35 | //把 1 左移 128 位,返回给 big.Int 36 | max := new(big.Int).Lsh(big.NewInt(1), 128) 37 | //返回在 [0, max) 区间均匀随机分布的一个随机值 38 | serialNumber, _ := rand.Int(rand.Reader, max) 39 | template := &x509.Certificate{ 40 | // SerialNumber 是 CA 颁布的唯一序列号,在此使用一个大随机数来代表它 41 | SerialNumber: serialNumber, 42 | Subject: pkix.Name{ // 证书的主题信息 43 | Country: []string{"CN"}, // 证书所属的国家 44 | Organization: []string{"MELF"}, // 证书存放的公司名称 45 | OrganizationalUnit: []string{"Guide"}, // 证书所属的部门名称 46 | Province: []string{"Shannxi"}, // 证书签发机构所在省 47 | CommonName: "guide.melf.sapce", // 证书域名 48 | Locality: []string{"Xian"}, // 证书签发机构所在市 49 | }, 50 | NotBefore: time.Now(), 51 | NotAfter: time.Now().AddDate(10, 0, 0), 52 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, // 典型用法是指定叶子证书中的公钥的使用目的。它包括一系列的OID,每一个都指定一种用途。例如{id pkix 31}表示用于服务器端的TLS/SSL连接;{id pkix 34}表示密钥可以用于保护电子邮件。 53 | KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, // 指定了这份证书包含的公钥可以执行的密码操作,例如只能用于签名,但不能用来加密 54 | IsCA: true, // 指示证书是不是ca证书 55 | BasicConstraintsValid: true, // 指示证书是不是ca证书 56 | } 57 | // 创建证书,这里第二个参数和第三个参数相同则表示该证书为自签证书,返回值为DER编码的证书 58 | certificate, err := x509.CreateCertificate(rand.Reader, template, template, publicKey, privateKey) 59 | if err != nil { 60 | return errors.New("生成自签证书失败:" + err.Error()) 61 | } 62 | // 将得到的证书放入pem.Block结构体中 63 | block := pem.Block{ 64 | Type: "CERTIFICATE", 65 | Bytes: certificate, 66 | } 67 | // 获取文件中的路径 68 | paths, _ := filepath.Split(caPath) 69 | // 创建文件夹 70 | err = os.MkdirAll(paths, os.ModePerm) 71 | if err != nil { 72 | return err 73 | } 74 | var file *os.File 75 | // 创建ca.crt(证书)文件 76 | file, err = os.Create(path.Join(caPath, "ca.crt")) 77 | defer file.Close() 78 | // 通过pem编码并写入磁盘文件 79 | err = pem.Encode(file, &block) 80 | if err != nil { 81 | return err 82 | } 83 | // 将私钥中的密钥对放入pem.Block结构体中 84 | block = pem.Block{ 85 | Type: "RSA PRIVATE KEY", 86 | Bytes: x509.MarshalPKCS1PrivateKey(privateKey), 87 | } 88 | // 创建ca.key(私钥)文件 89 | file, err = os.Create(path.Join(caPath, "ca.key")) 90 | if err != nil { 91 | return 92 | } 93 | // 通过pem编码并写入磁盘文件 94 | err = pem.Encode(file, &block) 95 | if err != nil { 96 | return err 97 | } 98 | return 99 | } 100 | 101 | // LoadCertificate 102 | /** 103 | * @Description: 读取CA证书 104 | * @param path CA证书路径 105 | * @return certificate CA证书 106 | * @return err 错误 107 | */ 108 | func LoadCertificate(path string) (certificate *x509.Certificate, err error) { 109 | // 打开文件读取私钥 110 | var file *os.File 111 | file, err = os.Open(path) 112 | if err != nil { 113 | return nil, err 114 | } 115 | defer file.Close() 116 | var fileInfo os.FileInfo 117 | fileInfo, err = file.Stat() 118 | if err != nil { 119 | return nil, err 120 | } 121 | buf := make([]byte, fileInfo.Size(), fileInfo.Size()) 122 | _, err = file.Read(buf) 123 | if err != nil { 124 | return nil, err 125 | } 126 | // 使用pem.Decode读取内容 127 | block, _ := pem.Decode(buf) 128 | if block == nil { 129 | err = errors.New("证书错误") 130 | return 131 | } 132 | certificate, err = x509.ParseCertificate(block.Bytes) 133 | if err != nil { 134 | return 135 | } 136 | return 137 | } 138 | -------------------------------------------------------------------------------- /rsa/rsa.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @Time :2022/6/6 15:37 3 | * @Author :Xiaoyu.Zhang 4 | */ 5 | 6 | package myrsa 7 | 8 | import ( 9 | "crypto/rand" 10 | "crypto/rsa" 11 | "crypto/x509" 12 | "encoding/hex" 13 | "encoding/pem" 14 | "errors" 15 | "os" 16 | "path/filepath" 17 | ) 18 | 19 | // GenerateRsaKey 20 | /** 21 | * @Description: 生成RSA公私钥 22 | * @param keySize 23 | * @return privateKey 24 | * @return publicKey 25 | * @return err 26 | */ 27 | func GenerateRsaKey(keySize int) (privateKey *rsa.PrivateKey, publicKey *rsa.PublicKey, err error) { 28 | privateKey, err = rsa.GenerateKey(rand.Reader, keySize) 29 | if err != nil { 30 | return 31 | } 32 | pubKey := privateKey.PublicKey 33 | publicKey = &pubKey 34 | return 35 | } 36 | 37 | // 参考文档:https://blog.csdn.net/lady_killer9/article/details/118026802 38 | 39 | // CreatePrivatePem 40 | /** 41 | * @Description: 创建PEM格式私钥文件 42 | * @param privateKey 私钥 43 | * @param path 私钥文件保存路径 44 | * @return err 错误 45 | */ 46 | func CreatePrivatePem(privateKey *rsa.PrivateKey, path string) (err error) { 47 | // 将私钥编码为pkcs1格式 48 | derText := x509.MarshalPKCS1PrivateKey(privateKey) 49 | // 使用pem.Block转为Block 50 | block := &pem.Block{ 51 | Type: "RSA PRIVATE KEY", 52 | Bytes: derText, 53 | } 54 | // 将私钥写入磁盘 55 | if path == "" { 56 | path = "cert/private.pem" 57 | } 58 | // 获取文件中的路径 59 | paths, _ := filepath.Split(path) 60 | err = os.MkdirAll(paths, os.ModePerm) 61 | if err != nil { 62 | return err 63 | } 64 | var file *os.File 65 | file, err = os.Create(path) 66 | if err != nil { 67 | return err 68 | } 69 | defer file.Close() 70 | // 使用pem.Encode写入文件 71 | err = pem.Encode(file, block) 72 | if err != nil { 73 | return 74 | } 75 | return 76 | } 77 | 78 | // CreatePublicPem 79 | /** 80 | * @Description: 创建PEM格式公钥文件 81 | * @param publicKey 公钥 82 | * @param path 私钥文件保存路径 83 | * @return err 错误 84 | */ 85 | func CreatePublicPem(publicKey *rsa.PublicKey, path string) (err error) { 86 | // 序列化公钥 87 | derStream := x509.MarshalPKCS1PublicKey(publicKey) 88 | // 使用pem.Block转为Block 89 | block := &pem.Block{ 90 | Type: "RSA PUBLIC KEY", 91 | Bytes: derStream, 92 | } 93 | // 将私钥写入磁盘 94 | if path == "" { 95 | path = "cert/public.pem" 96 | } 97 | // 获取文件中的路径 98 | paths, _ := filepath.Split(path) 99 | err = os.MkdirAll(paths, os.ModePerm) 100 | if err != nil { 101 | return err 102 | } 103 | var file *os.File 104 | file, err = os.Create(path) 105 | if err != nil { 106 | return err 107 | } 108 | defer file.Close() 109 | // 使用pem.Encode写入文件 110 | err = pem.Encode(file, block) 111 | if err != nil { 112 | return 113 | } 114 | return 115 | } 116 | 117 | // ReadPrivatePem 118 | /** 119 | * @Description: 读取PEM格式私钥 120 | * @param path 私钥文件保存路径 121 | * @return privateKey 私钥 122 | * @return err 错误 123 | */ 124 | func ReadPrivatePem(path string) (privateKey *rsa.PrivateKey, err error) { 125 | // 打开文件读取私钥 126 | var file *os.File 127 | file, err = os.Open(path) 128 | if err != nil { 129 | return nil, err 130 | } 131 | defer file.Close() 132 | var fileInfo os.FileInfo 133 | fileInfo, err = file.Stat() 134 | if err != nil { 135 | return nil, err 136 | } 137 | buf := make([]byte, fileInfo.Size(), fileInfo.Size()) 138 | _, err = file.Read(buf) 139 | if err != nil { 140 | return nil, err 141 | } 142 | // 使用pem.Decode读取内容 143 | block, _ := pem.Decode(buf) 144 | if block == nil { 145 | err = errors.New("私钥错误") 146 | return 147 | } 148 | // 将pem格式私钥文件进行反序列化 149 | privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) 150 | if err != nil { 151 | err = errors.New("私钥错误:" + err.Error()) 152 | return 153 | } 154 | return 155 | } 156 | 157 | // 参考文档:https://ask.csdn.net/questions/1012311 158 | 159 | // ReadPublicPem 160 | /** 161 | * @Description: 读取PEM格式公钥 162 | * @param path 公钥文件保存路径 163 | * @return publicKey 公钥 164 | * @return err 错误 165 | */ 166 | func ReadPublicPem(path string) (publicKey *rsa.PublicKey, err error) { 167 | // 打开文件读取私钥 168 | var file *os.File 169 | file, err = os.Open(path) 170 | if err != nil { 171 | return nil, err 172 | } 173 | defer file.Close() 174 | var fileInfo os.FileInfo 175 | fileInfo, err = file.Stat() 176 | if err != nil { 177 | return nil, err 178 | } 179 | buf := make([]byte, fileInfo.Size(), fileInfo.Size()) 180 | _, err = file.Read(buf) 181 | if err != nil { 182 | return nil, err 183 | } 184 | // 使用pem.Decode读取内容 185 | block, _ := pem.Decode(buf) 186 | if block == nil { 187 | err = errors.New("公钥错误") 188 | return 189 | } 190 | // 将pem格式公钥文件进行反序列化 191 | publicKey, err = x509.ParsePKCS1PublicKey(block.Bytes) 192 | if err != nil { 193 | err = errors.New("公钥错误:" + err.Error()) 194 | return 195 | } 196 | return 197 | } 198 | 199 | // CreatePrivateEC 200 | /** 201 | * @Description: 创建EC格式私钥文件 202 | * @param privateKey 私钥 203 | * @param path 私钥文件保存路径 204 | * @return err 错误 205 | */ 206 | func CreatePrivateEC(privateKey *rsa.PrivateKey, path string) (err error) { 207 | // 将私钥编码为pkcs8格式 208 | derText, err := x509.MarshalPKCS8PrivateKey(privateKey) 209 | if err != nil { 210 | return 211 | } 212 | // 使用pem.Block转为Block 213 | block := &pem.Block{ 214 | Type: "EC PRIVATE KEY", 215 | Bytes: derText, 216 | } 217 | // 将私钥写入磁盘 218 | if path == "" { 219 | path = "cert/private.key" 220 | } 221 | // 获取文件中的路径 222 | paths, _ := filepath.Split(path) 223 | err = os.MkdirAll(paths, os.ModePerm) 224 | if err != nil { 225 | return err 226 | } 227 | var file *os.File 228 | file, err = os.Create(path) 229 | // 将私钥转为pem格式 230 | if err = pem.Encode(file, block); err != nil { 231 | panic(err) 232 | } 233 | file.Close() 234 | return 235 | } 236 | 237 | // CreatePublicEC 238 | /** 239 | * @Description: 创建EC格式公钥文件 240 | * @param privateKey 公钥 241 | * @param path 公钥文件保存路径 242 | * @return err 错误 243 | */ 244 | func CreatePublicEC(publicKey *rsa.PublicKey, path string) (err error) { 245 | // 将私钥编码为pkcs8格式 246 | derText, err := x509.MarshalPKIXPublicKey(publicKey) 247 | if err != nil { 248 | return 249 | } 250 | // 使用pem.Block转为Block 251 | block := &pem.Block{ 252 | Type: "EC PUBLIC KEY", 253 | Bytes: derText, 254 | } 255 | // 将私钥写入磁盘 256 | if path == "" { 257 | path = "cert/public.key" 258 | } 259 | // 获取文件中的路径 260 | paths, _ := filepath.Split(path) 261 | err = os.MkdirAll(paths, os.ModePerm) 262 | if err != nil { 263 | return err 264 | } 265 | var file *os.File 266 | file, err = os.Create(path) 267 | // 将私钥转为pem格式 268 | if err = pem.Encode(file, block); err != nil { 269 | panic(err) 270 | } 271 | defer file.Close() 272 | return 273 | } 274 | 275 | // ReadPrivateEC 276 | /** 277 | * @Description: 读取EC格式私钥 278 | * @param path 私钥文件保存路径 279 | * @return privateKey 私钥 280 | * @return err 错误 281 | */ 282 | func ReadPrivateEC(path string) (privateKey *rsa.PrivateKey, err error) { 283 | // 打开文件读取私钥 284 | var file *os.File 285 | file, err = os.Open(path) 286 | if err != nil { 287 | return nil, err 288 | } 289 | defer file.Close() 290 | var fileInfo os.FileInfo 291 | fileInfo, err = file.Stat() 292 | if err != nil { 293 | return nil, err 294 | } 295 | buf := make([]byte, fileInfo.Size(), fileInfo.Size()) 296 | _, err = file.Read(buf) 297 | if err != nil { 298 | return nil, err 299 | } 300 | // 使用pem.Decode读取内容 301 | block, _ := pem.Decode(buf) 302 | if block == nil { 303 | err = errors.New("私钥错误") 304 | return 305 | } 306 | // 将pem格式私钥文件进行反序列化 307 | private, err := x509.ParsePKCS8PrivateKey(block.Bytes) 308 | if err != nil { 309 | err = errors.New("私钥错误:" + err.Error()) 310 | return 311 | } 312 | return private.(*rsa.PrivateKey), nil 313 | } 314 | 315 | // ReadPublicEC 316 | /** 317 | * @Description: 读取EC格式公钥 318 | * @param path 公钥文件保存路径 319 | * @return privateKey 私钥 320 | * @return err 错误 321 | */ 322 | func ReadPublicEC(path string) (publicKey *rsa.PublicKey, err error) { 323 | // 打开文件读取私钥 324 | var file *os.File 325 | file, err = os.Open(path) 326 | if err != nil { 327 | return nil, err 328 | } 329 | defer file.Close() 330 | var fileInfo os.FileInfo 331 | fileInfo, err = file.Stat() 332 | if err != nil { 333 | return nil, err 334 | } 335 | buf := make([]byte, fileInfo.Size(), fileInfo.Size()) 336 | _, err = file.Read(buf) 337 | if err != nil { 338 | return nil, err 339 | } 340 | // 使用pem.Decode读取内容 341 | block, _ := pem.Decode(buf) 342 | if block == nil { 343 | err = errors.New("公钥错误") 344 | return 345 | } 346 | // 将pem格式公钥文件进行反序列化 347 | public, err := x509.ParsePKIXPublicKey(block.Bytes) 348 | if err != nil { 349 | err = errors.New("公钥错误:" + err.Error()) 350 | return 351 | } 352 | return public.(*rsa.PublicKey), nil 353 | } 354 | 355 | // 参考文档:https://blog.csdn.net/lady_killer9/article/details/118026802 356 | 357 | // RsaEncrypt 358 | /** 359 | * @Description: RSA加密 360 | * @param publicKey 公钥 361 | * @param data 需要解密的内容 362 | * @return cipherText 加密后的内容 363 | * @return error 错误 364 | */ 365 | func RsaEncrypt(publicKey *rsa.PublicKey, data string) (cipherText string, err error) { 366 | // 将内容转换为[]byte 367 | dateByte := []byte(data) 368 | // 加密 369 | cipherByte, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, dateByte) 370 | if err != nil { 371 | return 372 | } 373 | // 将其装换为16进制字符串 374 | cipherText = hex.EncodeToString(cipherByte) 375 | return cipherText, nil 376 | } 377 | 378 | // RsaDecrypt 379 | /** 380 | * @Description: RSA解密 381 | * @param privateKey 私钥 382 | * @param cipherText 加密后的字符串 383 | * @return data 解密后的内容 384 | * @return err 错误 385 | */ 386 | func RsaDecrypt(privateKey *rsa.PrivateKey, cipherText string) (data string, err error) { 387 | // 将加密的16进制字符串装换为[]byte 388 | cipherByte, err := hex.DecodeString(cipherText) 389 | if err != nil { 390 | return 391 | } 392 | // 解密 393 | plainText, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherByte) 394 | if err != nil { 395 | return 396 | } 397 | data = string(plainText) 398 | return data, nil 399 | } 400 | -------------------------------------------------------------------------------- /sha1withrsa/sha1withrsa.go: -------------------------------------------------------------------------------- 1 | /** 2 | * @Time :2022/6/6 15:14 3 | * @Author :Xiaoyu.Zhang 4 | */ 5 | 6 | package sha1withrsa 7 | 8 | import ( 9 | "crypto" 10 | "crypto/rand" 11 | "crypto/rsa" 12 | "encoding/base64" 13 | ) 14 | 15 | // Sign 16 | /** 17 | * @Description: sha1withrsa 签名 18 | * @param privateKey 私钥 19 | * @param content 需要签名的内容 20 | * @return sign 签名 21 | * @return err 错误 22 | */ 23 | func Sign(privateKey *rsa.PrivateKey, content string) (sign string, err error) { 24 | h := crypto.Hash.New(crypto.SHA1) 25 | h.Write([]byte(content)) 26 | hashed := h.Sum(nil) 27 | var signature []byte 28 | signature, err = rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA1, hashed) 29 | if err != nil { 30 | return 31 | } 32 | sign = base64.StdEncoding.EncodeToString(signature) 33 | return 34 | } 35 | 36 | // RSAVerify 37 | /** 38 | * @Description: 验签 39 | * @param publicKey 公钥 40 | * @param originalData 原始数据 41 | * @param ciphertext 签名 42 | * @return ok 验签结果 43 | * @return error 错误 44 | */ 45 | func RSAVerify(publicKey *rsa.PublicKey, originalData, ciphertext string) (ok bool, err error) { 46 | h := crypto.Hash.New(crypto.SHA1) 47 | h.Write([]byte(originalData)) 48 | digest := h.Sum(nil) 49 | body, err := base64.StdEncoding.DecodeString(ciphertext) 50 | if err != nil { 51 | return false, err 52 | } 53 | err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA1, digest, body) 54 | if err != nil { 55 | return false, err 56 | } 57 | return true, nil 58 | } 59 | --------------------------------------------------------------------------------