gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/x509/utils.go (about) 1 // Copyright (c) 2022 zhaochun 2 // core-gm is licensed under Mulan PSL v2. 3 // You can use this software according to the terms and conditions of the Mulan PSL v2. 4 // You may obtain a copy of Mulan PSL v2 at: 5 // http://license.coscl.org.cn/MulanPSL2 6 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 7 // See the Mulan PSL v2 for more details. 8 9 package x509 10 11 /* 12 x509/utils.go 提供gmx509常用操作的公开函数: 13 ReadPrivateKeyFromPem : 将pem字节数组转为对应私钥 14 ReadPrivateKeyFromPemFile : 将pem文件转为对应私钥 15 WritePrivateKeyToPem : 将私钥转为pem字节数组 16 WritePrivateKeytoPemFile : 将私钥转为pem文件 17 ReadPublicKeyFromPem : 将pem字节数组转为对应公钥 18 ReadPublicKeyFromPemFile : 将pem文件转为对应公钥 19 WritePublicKeyToPem : 将公钥转为pem字节数组 20 WritePublicKeytoPemFile : 将公钥转为pem文件 21 ReadSm2PrivFromHex : 将hex字符串转为sm2私钥 22 WriteSm2PrivToHex : 将sm2私钥D转为hex字符串 23 ReadSm2PubFromHex : 将hex字符串转为sm2公钥 24 WriteSm2PubToHex : 将sm2公钥转为hex字符串 25 ReadCertificateRequestFromPem : 将pem字节数组转为证书申请 26 ReadCertificateRequestFromPemFile : 将pem文件转为证书申请 27 CreateCertificateRequestToPem : 创建证书申请并转为pem字节数组 28 CreateCertificateRequestToPemFile : 创建证书申请并转为pem文件 29 ReadCertificateFromPem : 将pem字节数组转为gmx509证书 30 ReadCertificateFromPemFile : 将pem文件转为gmx509证书 31 CreateCertificateToPem : 创建gmx509证书并转为pem字节数组 32 CreateCertificateToPemFile : 创建gmx509证书并转为pem文件 33 ParseGmx509DerToX509 : 将gmx509证书DER字节数组转为x509证书 34 CreateEllipticSKI : 根据椭圆曲线公钥参数生成其SKI值 35 GetRandBigInt : 随机生成序列号 36 ReadKeyFromPem : 从pem读取对称加密密钥 37 ReadKeyFromPemFile : 从pem文件读取对称加密密钥 38 WriteKeyToPem : 将对称加密密钥写入pem 39 WriteKeyToPemFile : 将对称加密密钥写入pem文件 40 */ 41 42 import ( 43 "crypto/ecdsa" 44 "crypto/ed25519" 45 "crypto/elliptic" 46 "crypto/rand" 47 "crypto/rsa" 48 "crypto/sha256" 49 "crypto/x509" 50 "encoding/pem" 51 "errors" 52 "fmt" 53 "gitee.com/ks-custle/core-gm/ecdsa_ext" 54 "io/ioutil" 55 "log" 56 "math/big" 57 "os" 58 "strings" 59 60 "gitee.com/ks-custle/core-gm/sm2" 61 ) 62 63 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 64 // 私钥与pem相互转换 65 66 // ReadPrivateKeyFromPem 将pem字节数组转为对应私钥 67 // - 私钥类型: *sm2.PrivateKey, *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey 68 // @param privateKeyPem 私钥pem字节数组 69 // @param pwd pem解密口令 70 // @return interface{} 返回私钥 71 // @return error 72 func ReadPrivateKeyFromPem(privateKeyPem []byte, pwd []byte) (interface{}, error) { 73 var block *pem.Block 74 block, _ = pem.Decode(privateKeyPem) 75 if block == nil { 76 return nil, errors.New("ReadPrivateKeyFromPem: pem decode failed") 77 } 78 blockType := strings.ToUpper(strings.TrimSpace(block.Type)) 79 if block == nil || !strings.HasSuffix(blockType, "PRIVATE KEY") { 80 return nil, errors.New("failed to decode private key") 81 } 82 var der []byte 83 var err error 84 if pwd != nil { 85 der, err = DecryptPEMBlock(block, pwd) 86 if err != nil { 87 return nil, err 88 } 89 } else { 90 der = block.Bytes 91 } 92 privKey, err := ParsePKCS8PrivateKey(der) 93 if err != nil { 94 if err.Error() == ErrMsgUseParseECPrivateKey { 95 privKey, err = ParseECPrivateKey(der) 96 } else if err.Error() == ErrMsgUseParsePKCS1PrivateKey { 97 privKey, err = ParsePKCS1PrivateKey(der) 98 } else { 99 return nil, err 100 } 101 } 102 // 对于ECDSA_EXT,需要封装为`ecdsa_ext.PrivateKey` 103 if blockType == "ECDSA_EXT PRIVATE KEY" { 104 if priv, ok := privKey.(*ecdsa.PrivateKey); ok { 105 return &ecdsa_ext.PrivateKey{ 106 PrivateKey: *priv, 107 }, nil 108 } 109 } 110 return privKey, err 111 } 112 113 // ReadPrivateKeyFromPemFile 将pem文件转为对应私钥 114 // - 私钥类型: *sm2.PrivateKey, *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey 115 // @param FileName pem文件路径 116 // @param pwd pem解密口令 117 // @return interface{} 返回私钥 118 // @return error 119 func ReadPrivateKeyFromPemFile(FileName string, pwd []byte) (interface{}, error) { 120 data, err := ioutil.ReadFile(FileName) 121 if err != nil { 122 return nil, err 123 } 124 return ReadPrivateKeyFromPem(data, pwd) 125 } 126 127 // WritePrivateKeyToPem 将私钥转为pem字节数组 128 // - 私钥类型: *sm2.PrivateKey, *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey 129 // @param key 私钥 130 // @param pwd pem加密口令 131 // @return []byte 私钥pem字节数组 132 // @return error 133 func WritePrivateKeyToPem(key interface{}, pwd []byte) ([]byte, error) { 134 var block *pem.Block 135 der, err := MarshalPKCS8PrivateKey(key) 136 if err != nil { 137 return nil, err 138 } 139 var pemType string 140 switch key.(type) { 141 case *sm2.PrivateKey: 142 pemType = "SM2 PRIVATE KEY" 143 case *ecdsa.PrivateKey: 144 pemType = "ECDSA PRIVATE KEY" 145 case *ecdsa_ext.PrivateKey: 146 pemType = "ECDSA_EXT PRIVATE KEY" 147 case ed25519.PrivateKey: 148 pemType = "ED25519 PRIVATE KEY" 149 case *rsa.PrivateKey: 150 pemType = "RSA PRIVATE KEY" 151 default: 152 return nil, fmt.Errorf("gmx509.WritePrivateKeyToPem : unsupported key: [%T]", key) 153 } 154 if pwd != nil { 155 block, err = EncryptPEMBlock(rand.Reader, "ENCRYPTED "+pemType, der, pwd, PEMCipherSM4) 156 if err != nil { 157 return nil, err 158 } 159 } else { 160 block = &pem.Block{ 161 Type: pemType, 162 Bytes: der, 163 } 164 } 165 certPem := pem.EncodeToMemory(block) 166 return certPem, nil 167 } 168 169 // WritePrivateKeytoPemFile 将私钥转为pem文件 170 // - 私钥类型: *sm2.PrivateKey, *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey 171 // @param FileName pem文件路径 172 // @param key 私钥 173 // @param pwd pem加密口令 174 // @return bool 成功与否 175 // @return error 176 func WritePrivateKeytoPemFile(FileName string, key interface{}, pwd []byte) (bool, error) { 177 var block *pem.Block 178 der, err := MarshalPKCS8PrivateKey(key) 179 if err != nil { 180 return false, err 181 } 182 var pemType string 183 switch key.(type) { 184 case *sm2.PrivateKey: 185 pemType = "SM2 PRIVATE KEY" 186 case *ecdsa.PrivateKey: 187 pemType = "ECDSA PRIVATE KEY" 188 case *ecdsa_ext.PrivateKey: 189 pemType = "ECDSA_EXT PRIVATE KEY" 190 case ed25519.PrivateKey: 191 pemType = "ED25519 PRIVATE KEY" 192 case *rsa.PrivateKey: 193 pemType = "RSA PRIVATE KEY" 194 default: 195 return false, fmt.Errorf("gmx509.WritePrivateKeytoPemFile : unsupported key: [%T]", key) 196 } 197 if pwd != nil { 198 block, err = EncryptPEMBlock(rand.Reader, "ENCRYPTED "+pemType, der, pwd, PEMCipherSM4) 199 if err != nil { 200 return false, err 201 } 202 } else { 203 block = &pem.Block{ 204 Type: pemType, 205 Bytes: der, 206 } 207 } 208 file, err := os.Create(FileName) 209 if err != nil { 210 return false, err 211 } 212 defer func(file *os.File) { 213 err := file.Close() 214 if err != nil { 215 log.Fatal(err) 216 } 217 }(file) 218 err = pem.Encode(file, block) 219 if err != nil { 220 return false, err 221 } 222 return true, nil 223 } 224 225 // 私钥与pem相互转换 226 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 227 228 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 229 // 公钥与pem相互转换 230 231 // ReadPublicKeyFromPem 将pem字节数组转为对应公钥 232 // - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey 233 // @param publicKeyPem 234 // @return interface{} 235 // @return error 236 func ReadPublicKeyFromPem(publicKeyPem []byte) (interface{}, error) { 237 block, _ := pem.Decode(publicKeyPem) 238 if block == nil { 239 return nil, errors.New("ReadPublicKeyFromPem: pem decode failed") 240 } 241 blockType := strings.ToUpper(strings.TrimSpace(block.Type)) 242 if block == nil || !strings.HasSuffix(blockType, "PUBLIC KEY") { 243 return nil, errors.New("failed to decode public key") 244 } 245 key, err := ParsePKIXPublicKey(block.Bytes) 246 if err != nil { 247 return nil, err 248 } 249 // 对于ECDSA_EXT需要包装为`ecdsa_ext.PublicKey` 250 if blockType == "ECDSA_EXT PUBLIC KEY" { 251 if pub, ok := key.(*ecdsa.PublicKey); ok { 252 return &ecdsa_ext.PublicKey{ 253 PublicKey: *pub, 254 }, nil 255 } 256 } 257 return key, nil 258 } 259 260 // ReadPublicKeyFromPemFile 将pem文件转为对应公钥 261 // - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey 262 // @param FileName 263 // @return interface{} 264 // @return error 265 func ReadPublicKeyFromPemFile(FileName string) (interface{}, error) { 266 data, err := ioutil.ReadFile(FileName) 267 if err != nil { 268 return nil, err 269 } 270 return ReadPublicKeyFromPem(data) 271 } 272 273 // WritePublicKeyToPem 将公钥转为pem字节数组 274 // 275 // - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey 276 // 277 // @param key 278 // @return []byte 279 // @return error 280 func WritePublicKeyToPem(key interface{}) ([]byte, error) { 281 der, err := MarshalPKIXPublicKey(key) 282 if err != nil { 283 return nil, err 284 } 285 var pemType string 286 switch key.(type) { 287 case *sm2.PublicKey: 288 pemType = "SM2 PUBLIC KEY" 289 case *ecdsa.PublicKey: 290 pemType = "ECDSA PUBLIC KEY" 291 case *ecdsa_ext.PublicKey: 292 pemType = "ECDSA_EXT PUBLIC KEY" 293 case ed25519.PublicKey: 294 pemType = "ED25519 PUBLIC KEY" 295 case *rsa.PublicKey: 296 pemType = "RSA PUBLIC KEY" 297 default: 298 return nil, fmt.Errorf("gmx509.WritePublicKeyToPem : unsupported key: [%T]", key) 299 } 300 block := &pem.Block{ 301 Type: pemType, 302 Bytes: der, 303 } 304 certPem := pem.EncodeToMemory(block) 305 return certPem, nil 306 } 307 308 // WritePublicKeytoPemFile 将公钥转为pem文件 309 // 310 // - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey 311 // 312 // @param FileName 313 // @param key 314 // @return bool 315 // @return error 316 func WritePublicKeytoPemFile(FileName string, key interface{}) (bool, error) { 317 der, err := MarshalPKIXPublicKey(key) 318 if err != nil { 319 return false, err 320 } 321 var pemType string 322 switch key.(type) { 323 case *sm2.PublicKey: 324 pemType = "SM2 PUBLIC KEY" 325 case *ecdsa.PublicKey: 326 pemType = "ECDSA PUBLIC KEY" 327 case *ecdsa_ext.PublicKey: 328 pemType = "ECDSA_EXT PUBLIC KEY" 329 case ed25519.PublicKey: 330 pemType = "ED25519 PUBLIC KEY" 331 case *rsa.PublicKey: 332 pemType = "RSA PUBLIC KEY" 333 default: 334 return false, fmt.Errorf("gmx509.WritePublicKeytoPemFile : unsupported key: [%T]", key) 335 } 336 block := &pem.Block{ 337 Type: pemType, 338 Bytes: der, 339 } 340 file, err := os.Create(FileName) 341 if err != nil { 342 return false, err 343 } 344 defer func(file *os.File) { 345 err := file.Close() 346 if err != nil { 347 log.Fatal(err) 348 } 349 }(file) 350 err = pem.Encode(file, block) 351 if err != nil { 352 return false, err 353 } 354 return true, nil 355 } 356 357 // 公钥与pem相互转换 358 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 359 360 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 361 // 证书申请与pem相互转换 362 363 // ReadCertificateRequestFromPem 将pem字节数组转为证书申请 364 // 365 // @param certPem 366 // @return *CertificateRequest 367 // @return error 368 func ReadCertificateRequestFromPem(certPem []byte) (*CertificateRequest, error) { 369 block, _ := pem.Decode(certPem) 370 if block == nil { 371 return nil, errors.New("failed to decode certificate request") 372 } 373 return ParseCertificateRequest(block.Bytes) 374 } 375 376 // ReadCertificateRequestFromPemFile 将pem文件转为证书申请 377 // 378 // @param FileName 379 // @return *CertificateRequest 380 // @return error 381 func ReadCertificateRequestFromPemFile(FileName string) (*CertificateRequest, error) { 382 data, err := ioutil.ReadFile(FileName) 383 if err != nil { 384 return nil, err 385 } 386 return ReadCertificateRequestFromPem(data) 387 } 388 389 // CreateCertificateRequestToPem 创建证书申请并转为pem字节数组 390 // 391 // @param template 392 // @param signer 393 // @return []byte 394 // @return error 395 func CreateCertificateRequestToPem(template *CertificateRequest, signer interface{}) ([]byte, error) { 396 der, err := CreateCertificateRequest(rand.Reader, template, signer) 397 if err != nil { 398 return nil, err 399 } 400 block := &pem.Block{ 401 Type: "CERTIFICATE REQUEST", 402 Bytes: der, 403 } 404 certPem := pem.EncodeToMemory(block) 405 return certPem, nil 406 } 407 408 // CreateCertificateRequestToPemFile 创建证书申请并转为pem文件 409 // 410 // @param FileName 411 // @param template 412 // @param signer 413 // @return bool 414 // @return error 415 func CreateCertificateRequestToPemFile(FileName string, template *CertificateRequest, signer interface{}) (bool, error) { 416 der, err := CreateCertificateRequest(rand.Reader, template, signer) 417 if err != nil { 418 return false, err 419 } 420 block := &pem.Block{ 421 Type: "CERTIFICATE REQUEST", 422 Bytes: der, 423 } 424 file, err := os.Create(FileName) 425 if err != nil { 426 return false, err 427 } 428 defer func(file *os.File) { 429 err := file.Close() 430 if err != nil { 431 log.Fatal(err) 432 } 433 }(file) 434 err = pem.Encode(file, block) 435 if err != nil { 436 return false, err 437 } 438 return true, nil 439 } 440 441 // 证书申请与pem相互转换 442 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 443 444 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 445 // gmx509证书与pem相互转换 446 447 // ReadCertificateFromPem 将pem字节数组转为gmx509证书 448 // 449 // @param certPem 450 // @return *Certificate 451 // @return error 452 func ReadCertificateFromPem(certPem []byte) (*Certificate, error) { 453 block, _ := pem.Decode(certPem) 454 if block == nil { 455 return nil, errors.New("failed to decode certificate request") 456 } 457 return ParseCertificate(block.Bytes) 458 } 459 460 // ReadCertificateFromPemFile 将pem文件转为gmx509证书 461 // 462 // @param FileName 463 // @return *Certificate 464 // @return error 465 func ReadCertificateFromPemFile(FileName string) (*Certificate, error) { 466 data, err := ioutil.ReadFile(FileName) 467 if err != nil { 468 return nil, err 469 } 470 return ReadCertificateFromPem(data) 471 } 472 473 // CreateCertificateToPem 创建gmx509证书并转为pem字节数组 474 // 475 // @param template 476 // @param parent 477 // @param pubKey 478 // @param signer 479 // @return []byte 480 // @return error 481 func CreateCertificateToPem(template, parent *Certificate, pubKey, signer interface{}) ([]byte, error) { 482 der, err := CreateCertificate(rand.Reader, template, parent, pubKey, signer) 483 if err != nil { 484 return nil, err 485 } 486 block := &pem.Block{ 487 Type: "CERTIFICATE", 488 Bytes: der, 489 } 490 certPem := pem.EncodeToMemory(block) 491 return certPem, nil 492 } 493 494 // CreateCertificateToPemFile 创建gmx509证书并转为pem文件 495 // 496 // @param FileName 497 // @param template 498 // @param parent 499 // @param pubKey 500 // @param privKey 501 // @return bool 502 // @return error 503 func CreateCertificateToPemFile(FileName string, template, parent *Certificate, pubKey, privKey interface{}) (bool, error) { 504 der, err := CreateCertificate(rand.Reader, template, parent, pubKey, privKey) 505 if err != nil { 506 return false, err 507 } 508 block := &pem.Block{ 509 Type: "CERTIFICATE", 510 Bytes: der, 511 } 512 file, err := os.Create(FileName) 513 if err != nil { 514 return false, err 515 } 516 defer func(file *os.File) { 517 _ = file.Close() 518 }(file) 519 err = pem.Encode(file, block) 520 if err != nil { 521 return false, err 522 } 523 return true, nil 524 } 525 526 // WriteCertificateToPem 将x509证书转为pem字节数组 527 // 528 // @param cert x509证书 529 // @return []byte pem字节数组 530 // 531 //goland:noinspection GoUnusedExportedFunction 532 func WriteCertificateToPem(cert *Certificate) []byte { 533 block := &pem.Block{ 534 Type: "CERTIFICATE", 535 Bytes: cert.Raw, 536 } 537 certPem := pem.EncodeToMemory(block) 538 return certPem 539 } 540 541 // WriteCertificateToPemFile 将x509证书转为pem文件 542 // 543 // @param path pem文件路径 544 // @param cert x509证书 545 // @return bool 546 // @return error 547 // 548 //goland:noinspection GoUnusedExportedFunction 549 func WriteCertificateToPemFile(path string, cert *Certificate) (bool, error) { 550 block := &pem.Block{ 551 Type: "CERTIFICATE", 552 Bytes: cert.Raw, 553 } 554 file, err := os.Create(path) 555 if err != nil { 556 return false, err 557 } 558 defer func(file *os.File) { 559 _ = file.Close() 560 }(file) 561 err = pem.Encode(file, block) 562 if err != nil { 563 return false, err 564 } 565 return true, nil 566 } 567 568 // gmx509证书与pem相互转换 569 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 570 571 // ParseGmx509DerToX509 将gmx509证书DER字节数组转为x509证书 572 // 573 // @param asn1data 574 // @return *x509.Certificate 575 // @return error 576 // 577 //goland:noinspection GoUnusedExportedFunction 578 func ParseGmx509DerToX509(asn1data []byte) (*x509.Certificate, error) { 579 sm2Cert, err := ParseCertificate(asn1data) 580 if err != nil { 581 return nil, err 582 } 583 return sm2Cert.ToX509Certificate(), nil 584 } 585 586 // CreateEllipticSKI 根据椭圆曲线公钥参数生成其SKI值 587 // 588 // @param curve 589 // @param x 590 // @param y 591 // @return []byte 592 func CreateEllipticSKI(curve elliptic.Curve, x, y *big.Int) []byte { 593 if curve == nil { 594 return nil 595 } 596 //Marshall the public key 597 raw := elliptic.Marshal(curve, x, y) 598 // Hash it 计算ski一律使用SHA256 599 hash := sha256.New() 600 hash.Write(raw) 601 return hash.Sum(nil) 602 } 603 604 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 605 // 对称加密密钥与pem相互转换 606 607 // ReadKeyFromPem 从pem读取对称加密密钥 608 func ReadKeyFromPem(data []byte, pwd []byte) ([]byte, error) { 609 block, _ := pem.Decode(data) 610 if block == nil { 611 return nil, errors.New("ReadKeyFromPem: pem decode failed") 612 } 613 blockType := strings.ToUpper(strings.TrimSpace(block.Type)) 614 if IsEncryptedPEMBlock(block) { 615 if !strings.HasSuffix(blockType, "ENCRYPTED KEY") { 616 return nil, errors.New("ReadKeyFromPem: unknown type") 617 } 618 if len(pwd) == 0 { 619 return nil, errors.New("ReadKeyFromPem: need passwd") 620 } 621 data, err := DecryptPEMBlock(block, pwd) 622 if err != nil { 623 return nil, err 624 } 625 return data, nil 626 } 627 switch blockType { 628 case "KEY", "SM4 KEY", "AES KEY", "SYMMETRIC KEY": 629 return block.Bytes, nil 630 default: 631 return nil, errors.New("ReadKeyFromPem: unknown type") 632 } 633 } 634 635 // ReadKeyFromPemFile 从pem文件读取对称加密密钥 636 func ReadKeyFromPemFile(FileName string, pwd []byte) ([]byte, error) { 637 data, err := ioutil.ReadFile(FileName) 638 if err != nil { 639 return nil, err 640 } 641 return ReadKeyFromPem(data, pwd) 642 } 643 644 // WriteKeyToPem 将对称加密密钥写入pem 645 func WriteKeyToPem(key []byte, pwd []byte) ([]byte, error) { 646 var block *pem.Block 647 var err error 648 if pwd != nil { 649 block, err = EncryptPEMBlock(rand.Reader, 650 "SYMMETRIC ENCRYPTED KEY", key, pwd, PEMCipherAES256) 651 } else { 652 block = &pem.Block{ 653 Type: "SYMMETRIC KEY", 654 Bytes: key, 655 } 656 } 657 if err != nil { 658 return nil, err 659 } 660 return pem.EncodeToMemory(block), nil 661 } 662 663 // WriteKeyToPemFile 将对称加密密钥写入pem文件 664 func WriteKeyToPemFile(FileName string, key []byte, pwd []byte) error { 665 pemBytes, err := WriteKeyToPem(key, pwd) 666 if err != nil { 667 return err 668 } 669 err = ioutil.WriteFile(FileName, pemBytes, 0666) 670 if err != nil { 671 return err 672 } 673 return nil 674 } 675 676 // 对称加密密钥与pem相互转换 677 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑