github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/x509/utils.go (about) 1 // Copyright 2022 s1ren@github.com/hxx258456. 2 3 package x509 4 5 /* 6 x509/utils.go 提供gmx509常用操作的公开函数: 7 ReadPrivateKeyFromPem : 将pem字节数组转为对应私钥 8 ReadPrivateKeyFromPemFile : 将pem文件转为对应私钥 9 WritePrivateKeyToPem : 将私钥转为pem字节数组 10 WritePrivateKeytoPemFile : 将私钥转为pem文件 11 ReadPublicKeyFromPem : 将pem字节数组转为对应公钥 12 ReadPublicKeyFromPemFile : 将pem文件转为对应公钥 13 WritePublicKeyToPem : 将公钥转为pem字节数组 14 WritePublicKeytoPemFile : 将公钥转为pem文件 15 ReadSm2PrivFromHex : 将hex字符串转为sm2私钥 16 WriteSm2PrivToHex : 将sm2私钥D转为hex字符串 17 ReadSm2PubFromHex : 将hex字符串转为sm2公钥 18 WriteSm2PubToHex : 将sm2公钥转为hex字符串 19 ReadCertificateRequestFromPem : 将pem字节数组转为证书申请 20 ReadCertificateRequestFromPemFile : 将pem文件转为证书申请 21 CreateCertificateRequestToPem : 创建证书申请并转为pem字节数组 22 CreateCertificateRequestToPemFile : 创建证书申请并转为pem文件 23 ReadCertificateFromPem : 将pem字节数组转为gmx509证书 24 ReadCertificateFromPemFile : 将pem文件转为gmx509证书 25 CreateCertificateToPem : 创建gmx509证书并转为pem字节数组 26 CreateCertificateToPemFile : 创建gmx509证书并转为pem文件 27 ParseGmx509DerToX509 : 将gmx509证书DER字节数组转为x509证书 28 CreateEllipticSKI : 根据椭圆曲线公钥参数生成其SKI值 29 GetRandBigInt : 随机生成序列号 30 */ 31 32 import ( 33 "crypto/ecdsa" 34 "crypto/ed25519" 35 "crypto/elliptic" 36 "crypto/rand" 37 "crypto/rsa" 38 "crypto/x509" 39 "encoding/pem" 40 "errors" 41 "fmt" 42 "io/ioutil" 43 "math/big" 44 "os" 45 "strings" 46 47 "gitee.com/zhaochuninhefei/zcgolog/zclog" 48 "github.com/hxx258456/ccgo/sm2" 49 "github.com/hxx258456/ccgo/sm3" 50 ) 51 52 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 53 // 私钥与pem相互转换 54 55 // ReadPrivateKeyFromPem 将pem字节数组转为对应私钥 56 // - 私钥类型: *sm2.PrivateKey, *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey 57 // @param privateKeyPem 私钥pem字节数组 58 // @param pwd pem解密口令 59 // @return interface{} 返回私钥 60 // @return error 61 func ReadPrivateKeyFromPem(privateKeyPem []byte, pwd []byte) (interface{}, error) { 62 var block *pem.Block 63 block, _ = pem.Decode(privateKeyPem) 64 if block == nil || !strings.HasSuffix(block.Type, "PRIVATE KEY") { 65 return nil, errors.New("failed to decode private key") 66 } 67 var der []byte 68 var err error 69 if pwd != nil { 70 der, err = DecryptPEMBlock(block, pwd) 71 if err != nil { 72 return nil, err 73 } 74 } else { 75 der = block.Bytes 76 } 77 return ParsePKCS8PrivateKey(der) 78 } 79 80 // ReadPrivateKeyFromPemFile 将pem文件转为对应私钥 81 // - 私钥类型: *sm2.PrivateKey, *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey 82 // @param FileName pem文件路径 83 // @param pwd pem解密口令 84 // @return interface{} 返回私钥 85 // @return error 86 func ReadPrivateKeyFromPemFile(FileName string, pwd []byte) (interface{}, error) { 87 data, err := ioutil.ReadFile(FileName) 88 if err != nil { 89 return nil, err 90 } 91 return ReadPrivateKeyFromPem(data, pwd) 92 } 93 94 // WritePrivateKeyToPem 将私钥转为pem字节数组 95 // - 私钥类型: *sm2.PrivateKey, *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey 96 // @param key 私钥 97 // @param pwd pem加密口令 98 // @return []byte 私钥pem字节数组 99 // @return error 100 func WritePrivateKeyToPem(key interface{}, pwd []byte) ([]byte, error) { 101 var block *pem.Block 102 der, err := MarshalPKCS8PrivateKey(key) 103 if err != nil { 104 return nil, err 105 } 106 var pemType string 107 switch key.(type) { 108 case *sm2.PrivateKey: 109 pemType = "SM2 PRIVATE KEY" 110 case *ecdsa.PrivateKey: 111 pemType = "ECDSA PRIVATE KEY" 112 case ed25519.PrivateKey: 113 pemType = "ED25519 PRIVATE KEY" 114 case *rsa.PrivateKey: 115 pemType = "RSA PRIVATE KEY" 116 default: 117 return nil, fmt.Errorf("gmx509.WritePrivateKeyToPem : unsupported key: [%T]", key) 118 } 119 if pwd != nil { 120 block, err = EncryptPEMBlock(rand.Reader, "ENCRYPTED "+pemType, der, pwd, PEMCipherSM4) 121 if err != nil { 122 return nil, err 123 } 124 } else { 125 block = &pem.Block{ 126 Type: pemType, 127 Bytes: der, 128 } 129 } 130 certPem := pem.EncodeToMemory(block) 131 return certPem, nil 132 } 133 134 // WritePrivateKeytoPemFile 将私钥转为pem文件 135 // - 私钥类型: *sm2.PrivateKey, *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey 136 // @param FileName pem文件路径 137 // @param key 私钥 138 // @param pwd pem加密口令 139 // @return bool 成功与否 140 // @return error 141 func WritePrivateKeytoPemFile(FileName string, key interface{}, pwd []byte) (bool, error) { 142 var block *pem.Block 143 der, err := MarshalPKCS8PrivateKey(key) 144 if err != nil { 145 return false, err 146 } 147 var pemType string 148 switch key.(type) { 149 case *sm2.PrivateKey: 150 pemType = "SM2 PRIVATE KEY" 151 case *ecdsa.PrivateKey: 152 pemType = "ECDSA PRIVATE KEY" 153 case ed25519.PrivateKey: 154 pemType = "ED25519 PRIVATE KEY" 155 case *rsa.PrivateKey: 156 pemType = "RSA PRIVATE KEY" 157 default: 158 return false, fmt.Errorf("gmx509.WritePrivateKeytoPemFile : unsupported key: [%T]", key) 159 } 160 if pwd != nil { 161 block, err = EncryptPEMBlock(rand.Reader, "ENCRYPTED "+pemType, der, pwd, PEMCipherSM4) 162 if err != nil { 163 return false, err 164 } 165 } else { 166 block = &pem.Block{ 167 Type: pemType, 168 Bytes: der, 169 } 170 } 171 file, err := os.Create(FileName) 172 if err != nil { 173 return false, err 174 } 175 defer func(file *os.File) { 176 err := file.Close() 177 if err != nil { 178 zclog.Errorln(err) 179 } 180 }(file) 181 err = pem.Encode(file, block) 182 if err != nil { 183 return false, err 184 } 185 return true, nil 186 } 187 188 // 私钥与pem相互转换 189 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 190 191 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 192 // 公钥与pem相互转换 193 194 // ReadPublicKeyFromPem 将pem字节数组转为对应公钥 195 // - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey 196 // @param publicKeyPem 197 // @return interface{} 198 // @return error 199 func ReadPublicKeyFromPem(publicKeyPem []byte) (interface{}, error) { 200 block, _ := pem.Decode(publicKeyPem) 201 if block == nil || !strings.HasSuffix(block.Type, "PUBLIC KEY") { 202 return nil, errors.New("failed to decode public key") 203 } 204 return ParsePKIXPublicKey(block.Bytes) 205 } 206 207 // ReadPublicKeyFromPemFile 将pem文件转为对应公钥 208 // - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey 209 // @param FileName 210 // @return interface{} 211 // @return error 212 func ReadPublicKeyFromPemFile(FileName string) (interface{}, error) { 213 data, err := ioutil.ReadFile(FileName) 214 if err != nil { 215 return nil, err 216 } 217 return ReadPublicKeyFromPem(data) 218 } 219 220 // WritePublicKeyToPem 将公钥转为pem字节数组 221 // 222 // - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey 223 // 224 // @param key 225 // @return []byte 226 // @return error 227 func WritePublicKeyToPem(key interface{}) ([]byte, error) { 228 der, err := MarshalPKIXPublicKey(key) 229 if err != nil { 230 return nil, err 231 } 232 var pemType string 233 switch key.(type) { 234 case *sm2.PublicKey: 235 pemType = "SM2 PUBLIC KEY" 236 case *ecdsa.PublicKey: 237 pemType = "ECDSA PUBLIC KEY" 238 case ed25519.PublicKey: 239 pemType = "ED25519 PUBLIC KEY" 240 case *rsa.PublicKey: 241 pemType = "RSA PUBLIC KEY" 242 default: 243 return nil, fmt.Errorf("gmx509.WritePublicKeyToPem : unsupported key: [%T]", key) 244 } 245 block := &pem.Block{ 246 Type: pemType, 247 Bytes: der, 248 } 249 certPem := pem.EncodeToMemory(block) 250 return certPem, nil 251 } 252 253 // WritePublicKeytoPemFile 将公钥转为pem文件 254 // 255 // - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey 256 // 257 // @param FileName 258 // @param key 259 // @return bool 260 // @return error 261 func WritePublicKeytoPemFile(FileName string, key interface{}) (bool, error) { 262 der, err := MarshalPKIXPublicKey(key) 263 if err != nil { 264 return false, err 265 } 266 var pemType string 267 switch key.(type) { 268 case *sm2.PublicKey: 269 pemType = "SM2 PUBLIC KEY" 270 case *ecdsa.PublicKey: 271 pemType = "ECDSA PUBLIC KEY" 272 case ed25519.PublicKey: 273 pemType = "ED25519 PUBLIC KEY" 274 case *rsa.PublicKey: 275 pemType = "RSA PUBLIC KEY" 276 default: 277 return false, fmt.Errorf("gmx509.WritePublicKeytoPemFile : unsupported key: [%T]", key) 278 } 279 block := &pem.Block{ 280 Type: pemType, 281 Bytes: der, 282 } 283 file, err := os.Create(FileName) 284 if err != nil { 285 return false, err 286 } 287 defer func(file *os.File) { 288 err := file.Close() 289 if err != nil { 290 zclog.Errorln(err) 291 } 292 }(file) 293 err = pem.Encode(file, block) 294 if err != nil { 295 return false, err 296 } 297 return true, nil 298 } 299 300 // 公钥与pem相互转换 301 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 302 303 // // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 304 // // SM2公私钥与hex相互转换 305 306 // // 将hex字符串转为sm2私钥 307 // // Dhex是16进制字符串,对应sm2.PrivateKey.D 308 // func ReadSm2PrivFromHex(Dhex string) (*sm2.PrivateKey, error) { 309 // c := sm2.P256Sm2() 310 // d, err := hex.DecodeString(Dhex) 311 // if err != nil { 312 // return nil, err 313 // } 314 // k := new(big.Int).SetBytes(d) 315 // params := c.Params() 316 // one := new(big.Int).SetInt64(1) 317 // n := new(big.Int).Sub(params.N, one) 318 // if k.Cmp(n) >= 0 { 319 // return nil, errors.New("privateKey's D is overflow") 320 // } 321 // priv := new(sm2.PrivateKey) 322 // priv.PublicKey.Curve = c 323 // priv.D = k 324 // priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes()) 325 // return priv, nil 326 // } 327 328 // // 将sm2私钥D转为hex字符串 329 // func WriteSm2PrivToHex(key *sm2.PrivateKey) string { 330 // return key.D.Text(16) 331 // } 332 333 // // 将hex字符串转为sm2公钥 334 // // Qhex是sm2公钥座标x,y的字节数组拼接后的hex转码字符串 335 // func ReadSm2PubFromHex(Qhex string) (*sm2.PublicKey, error) { 336 // q, err := hex.DecodeString(Qhex) 337 // if err != nil { 338 // return nil, err 339 // } 340 // if len(q) == 65 && q[0] == byte(0x04) { 341 // q = q[1:] 342 // } 343 // if len(q) != 64 { 344 // return nil, errors.New("publicKey is not uncompressed") 345 // } 346 // pub := new(sm2.PublicKey) 347 // pub.Curve = sm2.P256Sm2() 348 // pub.X = new(big.Int).SetBytes(q[:32]) 349 // pub.Y = new(big.Int).SetBytes(q[32:]) 350 // return pub, nil 351 // } 352 353 // // 将sm2公钥转为hex字符串 354 // func WriteSm2PubToHex(key *sm2.PublicKey) string { 355 // x := key.X.Bytes() 356 // y := key.Y.Bytes() 357 // if n := len(x); n < 32 { 358 // x = append(utils.ZeroByteSlice()[:32-n], x...) 359 // } 360 // if n := len(y); n < 32 { 361 // y = append(utils.ZeroByteSlice()[:32-n], y...) 362 // } 363 // c := []byte{} 364 // c = append(c, x...) 365 // c = append(c, y...) 366 // c = append([]byte{0x04}, c...) 367 // return hex.EncodeToString(c) 368 // } 369 370 // // SM2公私钥与hex相互转换 371 // // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 372 373 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 374 // 证书申请与pem相互转换 375 376 // ReadCertificateRequestFromPem 将pem字节数组转为证书申请 377 // 378 // @param certPem 379 // @return *CertificateRequest 380 // @return error 381 func ReadCertificateRequestFromPem(certPem []byte) (*CertificateRequest, error) { 382 block, _ := pem.Decode(certPem) 383 if block == nil { 384 return nil, errors.New("failed to decode certificate request") 385 } 386 return ParseCertificateRequest(block.Bytes) 387 } 388 389 // ReadCertificateRequestFromPemFile 将pem文件转为证书申请 390 // 391 // @param FileName 392 // @return *CertificateRequest 393 // @return error 394 func ReadCertificateRequestFromPemFile(FileName string) (*CertificateRequest, error) { 395 data, err := ioutil.ReadFile(FileName) 396 if err != nil { 397 return nil, err 398 } 399 return ReadCertificateRequestFromPem(data) 400 } 401 402 // CreateCertificateRequestToPem 创建证书申请并转为pem字节数组 403 // 404 // @param template 405 // @param signer 406 // @return []byte 407 // @return error 408 func CreateCertificateRequestToPem(template *CertificateRequest, signer interface{}) ([]byte, error) { 409 der, err := CreateCertificateRequest(rand.Reader, template, signer) 410 if err != nil { 411 return nil, err 412 } 413 block := &pem.Block{ 414 Type: "CERTIFICATE REQUEST", 415 Bytes: der, 416 } 417 certPem := pem.EncodeToMemory(block) 418 return certPem, nil 419 } 420 421 // CreateCertificateRequestToPemFile 创建证书申请并转为pem文件 422 // 423 // @param FileName 424 // @param template 425 // @param signer 426 // @return bool 427 // @return error 428 func CreateCertificateRequestToPemFile(FileName string, template *CertificateRequest, signer interface{}) (bool, error) { 429 der, err := CreateCertificateRequest(rand.Reader, template, signer) 430 if err != nil { 431 return false, err 432 } 433 block := &pem.Block{ 434 Type: "CERTIFICATE REQUEST", 435 Bytes: der, 436 } 437 file, err := os.Create(FileName) 438 if err != nil { 439 return false, err 440 } 441 defer func(file *os.File) { 442 err := file.Close() 443 if err != nil { 444 zclog.Errorln(err) 445 } 446 }(file) 447 err = pem.Encode(file, block) 448 if err != nil { 449 return false, err 450 } 451 return true, nil 452 } 453 454 // 证书申请与pem相互转换 455 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 456 457 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 458 // gmx509证书与pem相互转换 459 460 // ReadCertificateFromPem 将pem字节数组转为gmx509证书 461 // 462 // @param certPem 463 // @return *Certificate 464 // @return error 465 func ReadCertificateFromPem(certPem []byte) (*Certificate, error) { 466 block, _ := pem.Decode(certPem) 467 if block == nil { 468 return nil, errors.New("failed to decode certificate request") 469 } 470 return ParseCertificate(block.Bytes) 471 } 472 473 // ReadCertificateFromPemFile 将pem文件转为gmx509证书 474 // 475 // @param FileName 476 // @return *Certificate 477 // @return error 478 func ReadCertificateFromPemFile(FileName string) (*Certificate, error) { 479 data, err := ioutil.ReadFile(FileName) 480 if err != nil { 481 return nil, err 482 } 483 return ReadCertificateFromPem(data) 484 } 485 486 // CreateCertificateToPem 创建gmx509证书并转为pem字节数组 487 // 488 // @param template 489 // @param parent 490 // @param pubKey 491 // @param signer 492 // @return []byte 493 // @return error 494 func CreateCertificateToPem(template, parent *Certificate, pubKey, signer interface{}) ([]byte, error) { 495 der, err := CreateCertificate(rand.Reader, template, parent, pubKey, signer) 496 if err != nil { 497 return nil, err 498 } 499 block := &pem.Block{ 500 Type: "CERTIFICATE", 501 Bytes: der, 502 } 503 certPem := pem.EncodeToMemory(block) 504 return certPem, nil 505 } 506 507 // CreateCertificateToPemFile 创建gmx509证书并转为pem文件 508 // 509 // @param FileName 510 // @param template 511 // @param parent 512 // @param pubKey 513 // @param privKey 514 // @return bool 515 // @return error 516 func CreateCertificateToPemFile(FileName string, template, parent *Certificate, pubKey, privKey interface{}) (bool, error) { 517 der, err := CreateCertificate(rand.Reader, template, parent, pubKey, privKey) 518 if err != nil { 519 return false, err 520 } 521 block := &pem.Block{ 522 Type: "CERTIFICATE", 523 Bytes: der, 524 } 525 file, err := os.Create(FileName) 526 if err != nil { 527 return false, err 528 } 529 defer func(file *os.File) { 530 err := file.Close() 531 if err != nil { 532 zclog.Errorln(err) 533 } 534 }(file) 535 err = pem.Encode(file, block) 536 if err != nil { 537 return false, err 538 } 539 return true, nil 540 } 541 542 // gmx509证书与pem相互转换 543 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 544 545 // ParseGmx509DerToX509 将gmx509证书DER字节数组转为x509证书 546 // 547 // @param asn1data 548 // @return *x509.Certificate 549 // @return error 550 // 551 //goland:noinspection GoUnusedExportedFunction 552 func ParseGmx509DerToX509(asn1data []byte) (*x509.Certificate, error) { 553 sm2Cert, err := ParseCertificate(asn1data) 554 if err != nil { 555 return nil, err 556 } 557 return sm2Cert.ToX509Certificate(), nil 558 } 559 560 // CreateEllipticSKI 根据椭圆曲线公钥参数生成其SKI值 561 // 562 // @param curve 563 // @param x 564 // @param y 565 // @return []byte 566 func CreateEllipticSKI(curve elliptic.Curve, x, y *big.Int) []byte { 567 if curve == nil { 568 return nil 569 } 570 //Marshall the public key 571 raw := elliptic.Marshal(curve, x, y) 572 // Hash it 国密改造后改为sm3 573 hash := sm3.New() 574 hash.Write(raw) 575 return hash.Sum(nil) 576 } 577 578 // GetRandBigInt 随机生成序列号 579 // 580 // @return *big.Int 581 func GetRandBigInt() *big.Int { 582 sn, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) 583 if err != nil { 584 panic(err) 585 } 586 return sn 587 }