github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/util/xcrypto/rsa_test.go (about) 1 package xcrypto 2 3 import ( 4 "crypto/rand" 5 "crypto/rsa" 6 "crypto/x509" 7 "encoding/pem" 8 "os" 9 "path/filepath" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 ) 14 15 const ( 16 PublicPemFile = "/test/testdata/rsa_public.pem" 17 PublicPKCS1PemFile = "/test/testdata/rsa_public_pkcs1.pem" 18 PrivatePemFile = "/test/testdata/rsa_private.pem" 19 PrivatePKCS1PemFile = "/test/testdata/rsa_private_pkcs1.pem" 20 ) 21 22 var ( 23 rootDir string 24 key []byte 25 origin []byte 26 iv []byte 27 ) 28 29 func TestMain(m *testing.M) { 30 //当前目录 31 currDir, _ := os.Getwd() 32 rootDir = filepath.Dir(filepath.Dir(currDir)) 33 // 声明一个16字节的key 34 key = []byte("example key 1234") 35 // 声明一个随意长度的 需加密内容 36 origin = []byte("need to crypto encode test text") 37 // 声明一个16字节的iv 38 iv = []byte("example iv tests") 39 m.Run() 40 } 41 42 // 生成RSA密钥对 43 func TestGenerateRSAKey(t *testing.T) { 44 // 声明位数 45 var bits = 1024 46 47 // 使用随机数据生成器random生成一对具有指定位数的RSA密钥 48 privateKey, err := rsa.GenerateKey(rand.Reader, bits) 49 50 // 使用指定的位数生成一对多质数的RSA密钥。(质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数) 51 // 虽然公钥可以和二质数情况下的公钥兼容(事实上,不能区分两种公钥),私钥却不行。 52 // 因此有可能无法生成特定格式的多质数的密钥对,或不能将生成的密钥用在其他(语言的)代码里 53 //privateKey, err := rsa.GenerateMultiPrimeKey(rand.Reader, 5, bits) 54 55 if err != nil { 56 t.Fatal(err) 57 } 58 59 // 将rsa私钥序列化为ASN.1 PKCS#1 DER编码 60 derPrivate := x509.MarshalPKCS1PrivateKey(privateKey) 61 // 初始化一个PEM编码的结构 62 priBlock := &pem.Block{ 63 Type: "PRIVATE KEY", 64 Bytes: derPrivate, 65 } 66 // 创建文件,如果文件存在内容重置为空 67 file, err := os.Create(rootDir + PrivatePKCS1PemFile) 68 if err != nil { 69 t.Fatal(err) 70 } 71 defer file.Close() 72 73 // 将Block的pem编码写入文件 74 err = pem.Encode(file, priBlock) 75 if err != nil { 76 t.Fatal(err) 77 } 78 t.Log("RSA-PKCS1私钥生成成功") 79 80 // 将rsa私钥序列化为PKCS#8 DER编码 81 derPrivate8, err := x509.MarshalPKCS8PrivateKey(privateKey) 82 if err != nil { 83 t.Fatal(err) 84 } 85 86 // 初始化一个PEM编码的结构 87 priBlock8 := &pem.Block{ 88 Type: "PRIVATE KEY", 89 Bytes: derPrivate8, 90 } 91 92 // 创建文件,如果文件存在内容重置为空 93 file2, err := os.Create(rootDir + PrivatePemFile) 94 if err != nil { 95 t.Fatal(err) 96 } 97 defer file2.Close() 98 99 // 将Block的pem编码写入文件 100 err = pem.Encode(file2, priBlock8) 101 if err != nil { 102 t.Fatal(err) 103 } 104 t.Log("RSA-PKCS8私钥生成成功") 105 106 // 获取公钥 107 publicKey := &privateKey.PublicKey 108 109 // 将公钥序列化为PKIX格式DER编码 110 derPublic, err := x509.MarshalPKIXPublicKey(publicKey) 111 if err != nil { 112 t.Fatal(err) 113 } 114 // 初始化一个PEM编码的结构 115 pubBlock := &pem.Block{ 116 Type: "PUBLIC KEY", 117 Bytes: derPublic, 118 } 119 120 // 创建文件,如果文件存在内容重置为空 121 file3, err := os.Create(rootDir + PublicPemFile) 122 if err != nil { 123 t.Fatal(err) 124 } 125 defer file3.Close() 126 127 // 将Block的pem编码写入文件 128 err = pem.Encode(file3, pubBlock) 129 if err != nil { 130 t.Fatal(err) 131 } 132 t.Log("RSA-PKIX公钥生成成功") 133 134 derPublic1 := x509.MarshalPKCS1PublicKey(publicKey) 135 // 初始化一个PEM编码的结构 136 pubBlock1 := &pem.Block{ 137 Type: "PUBLIC KEY", 138 Bytes: derPublic1, 139 } 140 // 创建文件,如果文件存在内容重置为空 141 file4, err := os.Create(rootDir + PublicPKCS1PemFile) 142 if err != nil { 143 t.Fatal(err) 144 } 145 defer file4.Close() 146 147 // 将Block的pem编码写入文件 148 err = pem.Encode(file4, pubBlock1) 149 if err != nil { 150 t.Fatal(err) 151 } 152 t.Log("RSA-PKCS1公钥生成成功") 153 } 154 155 // 使用PKCS#1v1.5规定的填充方案和RSA公钥加密/私钥解密 156 func TestRSAPKCS1v15(t *testing.T) { 157 // 获取公钥私钥 158 privateKey, publicKey, err := getRSAKey() 159 if err != nil { 160 t.Fatal(err) 161 } 162 163 // rsa公钥加密 164 cipherText, err := RsaEncrypt(publicKey, origin) 165 if err != nil { 166 t.Fatal(err) 167 } 168 169 // rsa私钥解密 170 originText, err := RsaDecrypt(privateKey, cipherText) 171 if err != nil { 172 t.Fatal(err) 173 } 174 assert.Equal(t, originText, origin) 175 } 176 177 // RSA-OAEP算法公钥加密/私钥解密 178 func TestRSAOAEP(t *testing.T) { 179 // 获取公钥私钥 180 privateKey, publicKey, err := getRSAKey() 181 if err != nil { 182 t.Fatal(err) 183 } 184 185 // 声明label 186 var label = []byte("test") 187 188 // rsa公钥加密 189 cipherText, err := RsaEncryptOAEP(publicKey, origin, label) 190 if err != nil { 191 t.Fatal(err) 192 } 193 194 // rsa私钥解密 195 originText, err := RsaDecryptOAEP(privateKey, cipherText, label) 196 if err != nil { 197 t.Fatal(err) 198 } 199 assert.Equal(t, originText, origin) 200 } 201 202 // RSA私钥签名/公钥验证 203 func TestRSASignature(t *testing.T) { 204 // 获取公钥私钥 205 privateKey, publicKey, err := getRSAKey() 206 if err != nil { 207 t.Fatal(err) 208 } 209 210 // rsa私钥签名 211 signature, err := RsaSign(privateKey, origin) 212 if err != nil { 213 t.Fatal(err) 214 } 215 216 //rsa公钥验签 217 if err = RsaVerify(publicKey, origin, signature); err != nil { 218 t.Fatal(err) 219 } 220 } 221 222 // RSA-PASS私钥签名/公钥验证 223 func TestRSASignPass(t *testing.T) { 224 // 获取公钥私钥 225 privateKey, publicKey, err := getRSAKey() 226 if err != nil { 227 t.Fatal(err) 228 } 229 230 // 初始化一个 PSS签名 的参数 231 var SignOpts = rsa.PSSOptions{SaltLength: 8} 232 233 // 初始化一个 PSS认证 的参数 234 var VerifyOpts = rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthAuto} 235 // 当PSS签名参数SaltLength 为 rsa.PSSSaltLengthAuto, PSS认证参数SaltLength 必须为 rsa.PSSSaltLengthAuto 236 // 当PSS签名参数SaltLength 为 rsa.PSSSaltLengthEqualsHash, PSS认证参数SaltLength 为 rsa.PSSSaltLengthAuto或rsa.PSSSaltLengthEqualsHash 237 // 当PSS签名参数SaltLength 为 指定值时 如8, PSS认证参数SaltLength 为rsa.PSSSaltLengthAuto或8 238 // 239 240 // rsa私钥签名 241 signature, err := RsaSignPass(privateKey, origin, &SignOpts) 242 if err != nil { 243 t.Fatal(err) 244 } 245 246 //rsa公钥验签 247 if err = RsaVerifyPass(publicKey, origin, signature, &VerifyOpts); err != nil { 248 t.Fatal(err) 249 } 250 } 251 252 func getRSAKey() (privateKey []byte, publicKey []byte, err error) { 253 254 // 读取publicKey内容 255 publicKey, err = os.ReadFile(rootDir + PublicPemFile) 256 if err != nil { 257 return 258 } 259 // 读取privateKey内容 260 privateKey, err = os.ReadFile(rootDir + PrivatePemFile) 261 return 262 }