gitee.com/zhaochuninhefei/gmgo@v0.0.31-0.20240209061119-069254a02979/x509/utils.go (about) 1 // Copyright (c) 2022 zhaochun 2 // gmgo 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/zhaochuninhefei/gmgo/ecdsa_ext" 54 "gitee.com/zhaochuninhefei/zcgolog/zclog" 55 "io/ioutil" 56 "math/big" 57 "os" 58 "strings" 59 60 "gitee.com/zhaochuninhefei/gmgo/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 zclog.Errorln(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 // - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey 275 // 276 // @param key 277 // @return []byte 278 // @return error 279 func WritePublicKeyToPem(key interface{}) ([]byte, error) { 280 der, err := MarshalPKIXPublicKey(key) 281 if err != nil { 282 return nil, err 283 } 284 var pemType string 285 switch key.(type) { 286 case *sm2.PublicKey: 287 pemType = "SM2 PUBLIC KEY" 288 case *ecdsa.PublicKey: 289 pemType = "ECDSA PUBLIC KEY" 290 case *ecdsa_ext.PublicKey: 291 pemType = "ECDSA_EXT PUBLIC KEY" 292 case ed25519.PublicKey: 293 pemType = "ED25519 PUBLIC KEY" 294 case *rsa.PublicKey: 295 pemType = "RSA PUBLIC KEY" 296 default: 297 return nil, fmt.Errorf("gmx509.WritePublicKeyToPem : unsupported key: [%T]", key) 298 } 299 block := &pem.Block{ 300 Type: pemType, 301 Bytes: der, 302 } 303 certPem := pem.EncodeToMemory(block) 304 return certPem, nil 305 } 306 307 // WritePublicKeytoPemFile 将公钥转为pem文件 308 // - 公钥类型: *sm2.PublicKey, *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey 309 // 310 // @param FileName 311 // @param key 312 // @return bool 313 // @return error 314 func WritePublicKeytoPemFile(FileName string, key interface{}) (bool, error) { 315 der, err := MarshalPKIXPublicKey(key) 316 if err != nil { 317 return false, err 318 } 319 var pemType string 320 switch key.(type) { 321 case *sm2.PublicKey: 322 pemType = "SM2 PUBLIC KEY" 323 case *ecdsa.PublicKey: 324 pemType = "ECDSA PUBLIC KEY" 325 case *ecdsa_ext.PublicKey: 326 pemType = "ECDSA_EXT PUBLIC KEY" 327 case ed25519.PublicKey: 328 pemType = "ED25519 PUBLIC KEY" 329 case *rsa.PublicKey: 330 pemType = "RSA PUBLIC KEY" 331 default: 332 return false, fmt.Errorf("gmx509.WritePublicKeytoPemFile : unsupported key: [%T]", key) 333 } 334 block := &pem.Block{ 335 Type: pemType, 336 Bytes: der, 337 } 338 file, err := os.Create(FileName) 339 if err != nil { 340 return false, err 341 } 342 defer func(file *os.File) { 343 err := file.Close() 344 if err != nil { 345 zclog.Errorln(err) 346 } 347 }(file) 348 err = pem.Encode(file, block) 349 if err != nil { 350 return false, err 351 } 352 return true, nil 353 } 354 355 // 公钥与pem相互转换 356 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 357 358 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 359 // 证书申请与pem相互转换 360 361 // ReadCertificateRequestFromPem 将pem字节数组转为证书申请 362 // 363 // @param certPem 364 // @return *CertificateRequest 365 // @return error 366 func ReadCertificateRequestFromPem(certPem []byte) (*CertificateRequest, error) { 367 block, _ := pem.Decode(certPem) 368 if block == nil { 369 return nil, errors.New("failed to decode certificate request") 370 } 371 return ParseCertificateRequest(block.Bytes) 372 } 373 374 // ReadCertificateRequestFromPemFile 将pem文件转为证书申请 375 // 376 // @param FileName 377 // @return *CertificateRequest 378 // @return error 379 func ReadCertificateRequestFromPemFile(FileName string) (*CertificateRequest, error) { 380 data, err := ioutil.ReadFile(FileName) 381 if err != nil { 382 return nil, err 383 } 384 return ReadCertificateRequestFromPem(data) 385 } 386 387 // CreateCertificateRequestToPem 创建证书申请并转为pem字节数组 388 // 389 // @param template 390 // @param signer 391 // @return []byte 392 // @return error 393 func CreateCertificateRequestToPem(template *CertificateRequest, signer interface{}) ([]byte, error) { 394 der, err := CreateCertificateRequest(rand.Reader, template, signer) 395 if err != nil { 396 return nil, err 397 } 398 block := &pem.Block{ 399 Type: "CERTIFICATE REQUEST", 400 Bytes: der, 401 } 402 certPem := pem.EncodeToMemory(block) 403 return certPem, nil 404 } 405 406 // CreateCertificateRequestToPemFile 创建证书申请并转为pem文件 407 // 408 // @param FileName 409 // @param template 410 // @param signer 411 // @return bool 412 // @return error 413 func CreateCertificateRequestToPemFile(FileName string, template *CertificateRequest, signer interface{}) (bool, error) { 414 der, err := CreateCertificateRequest(rand.Reader, template, signer) 415 if err != nil { 416 return false, err 417 } 418 block := &pem.Block{ 419 Type: "CERTIFICATE REQUEST", 420 Bytes: der, 421 } 422 file, err := os.Create(FileName) 423 if err != nil { 424 return false, err 425 } 426 defer func(file *os.File) { 427 err := file.Close() 428 if err != nil { 429 zclog.Errorln(err) 430 } 431 }(file) 432 err = pem.Encode(file, block) 433 if err != nil { 434 return false, err 435 } 436 return true, nil 437 } 438 439 // 证书申请与pem相互转换 440 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 441 442 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 443 // gmx509证书与pem相互转换 444 445 // ReadCertificateFromPem 将pem字节数组转为gmx509证书 446 // 447 // @param certPem 448 // @return *Certificate 449 // @return error 450 func ReadCertificateFromPem(certPem []byte) (*Certificate, error) { 451 block, _ := pem.Decode(certPem) 452 if block == nil { 453 return nil, errors.New("failed to decode certificate request") 454 } 455 return ParseCertificate(block.Bytes) 456 } 457 458 // ReadCertificateFromPemFile 将pem文件转为gmx509证书 459 // 460 // @param FileName 461 // @return *Certificate 462 // @return error 463 func ReadCertificateFromPemFile(FileName string) (*Certificate, error) { 464 data, err := ioutil.ReadFile(FileName) 465 if err != nil { 466 return nil, err 467 } 468 return ReadCertificateFromPem(data) 469 } 470 471 // CreateCertificateToPem 创建gmx509证书并转为pem字节数组 472 // 473 // @param template 474 // @param parent 475 // @param pubKey 476 // @param signer 477 // @return []byte 478 // @return error 479 func CreateCertificateToPem(template, parent *Certificate, pubKey, signer interface{}) ([]byte, error) { 480 der, err := CreateCertificate(rand.Reader, template, parent, pubKey, signer) 481 if err != nil { 482 return nil, err 483 } 484 block := &pem.Block{ 485 Type: "CERTIFICATE", 486 Bytes: der, 487 } 488 certPem := pem.EncodeToMemory(block) 489 return certPem, nil 490 } 491 492 // CreateCertificateToPemFile 创建gmx509证书并转为pem文件 493 // 494 // @param FileName 495 // @param template 496 // @param parent 497 // @param pubKey 498 // @param privKey 499 // @return bool 500 // @return error 501 func CreateCertificateToPemFile(FileName string, template, parent *Certificate, pubKey, privKey interface{}) (bool, error) { 502 der, err := CreateCertificate(rand.Reader, template, parent, pubKey, privKey) 503 if err != nil { 504 return false, err 505 } 506 block := &pem.Block{ 507 Type: "CERTIFICATE", 508 Bytes: der, 509 } 510 file, err := os.Create(FileName) 511 if err != nil { 512 return false, err 513 } 514 defer func(file *os.File) { 515 _ = file.Close() 516 }(file) 517 err = pem.Encode(file, block) 518 if err != nil { 519 return false, err 520 } 521 return true, nil 522 } 523 524 // WriteCertificateToPem 将x509证书转为pem字节数组 525 // @param cert x509证书 526 // @return []byte pem字节数组 527 //goland:noinspection GoUnusedExportedFunction 528 func WriteCertificateToPem(cert *Certificate) []byte { 529 block := &pem.Block{ 530 Type: "CERTIFICATE", 531 Bytes: cert.Raw, 532 } 533 certPem := pem.EncodeToMemory(block) 534 return certPem 535 } 536 537 // WriteCertificateToPemFile 将x509证书转为pem文件 538 // @param path pem文件路径 539 // @param cert x509证书 540 // @return bool 541 // @return error 542 //goland:noinspection GoUnusedExportedFunction 543 func WriteCertificateToPemFile(path string, cert *Certificate) (bool, error) { 544 block := &pem.Block{ 545 Type: "CERTIFICATE", 546 Bytes: cert.Raw, 547 } 548 file, err := os.Create(path) 549 if err != nil { 550 return false, err 551 } 552 defer func(file *os.File) { 553 _ = file.Close() 554 }(file) 555 err = pem.Encode(file, block) 556 if err != nil { 557 return false, err 558 } 559 return true, nil 560 } 561 562 // gmx509证书与pem相互转换 563 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 564 565 // ParseGmx509DerToX509 将gmx509证书DER字节数组转为x509证书 566 // 567 // @param asn1data 568 // @return *x509.Certificate 569 // @return error 570 //goland:noinspection GoUnusedExportedFunction 571 func ParseGmx509DerToX509(asn1data []byte) (*x509.Certificate, error) { 572 sm2Cert, err := ParseCertificate(asn1data) 573 if err != nil { 574 return nil, err 575 } 576 return sm2Cert.ToX509Certificate(), nil 577 } 578 579 // CreateEllipticSKI 根据椭圆曲线公钥参数生成其SKI值 580 // 581 // @param curve 582 // @param x 583 // @param y 584 // @return []byte 585 func CreateEllipticSKI(curve elliptic.Curve, x, y *big.Int) []byte { 586 if curve == nil { 587 return nil 588 } 589 //Marshall the public key 590 raw := elliptic.Marshal(curve, x, y) 591 // Hash it 计算ski一律使用SHA256 592 hash := sha256.New() 593 hash.Write(raw) 594 return hash.Sum(nil) 595 } 596 597 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 598 // 对称加密密钥与pem相互转换 599 600 // ReadKeyFromPem 从pem读取对称加密密钥 601 func ReadKeyFromPem(data []byte, pwd []byte) ([]byte, error) { 602 block, _ := pem.Decode(data) 603 if block == nil { 604 return nil, errors.New("ReadKeyFromPem: pem decode failed") 605 } 606 blockType := strings.ToUpper(strings.TrimSpace(block.Type)) 607 if IsEncryptedPEMBlock(block) { 608 if !strings.HasSuffix(blockType, "ENCRYPTED KEY") { 609 return nil, errors.New("ReadKeyFromPem: unknown type") 610 } 611 if len(pwd) == 0 { 612 return nil, errors.New("ReadKeyFromPem: need passwd") 613 } 614 data, err := DecryptPEMBlock(block, pwd) 615 if err != nil { 616 return nil, err 617 } 618 return data, nil 619 } 620 switch blockType { 621 case "KEY", "SM4 KEY", "AES KEY", "SYMMETRIC KEY": 622 return block.Bytes, nil 623 default: 624 return nil, errors.New("ReadKeyFromPem: unknown type") 625 } 626 } 627 628 // ReadKeyFromPemFile 从pem文件读取对称加密密钥 629 func ReadKeyFromPemFile(FileName string, pwd []byte) ([]byte, error) { 630 data, err := ioutil.ReadFile(FileName) 631 if err != nil { 632 return nil, err 633 } 634 return ReadKeyFromPem(data, pwd) 635 } 636 637 // WriteKeyToPem 将对称加密密钥写入pem 638 func WriteKeyToPem(key []byte, pwd []byte) ([]byte, error) { 639 var block *pem.Block 640 var err error 641 if pwd != nil { 642 block, err = EncryptPEMBlock(rand.Reader, 643 "SYMMETRIC ENCRYPTED KEY", key, pwd, PEMCipherAES256) 644 } else { 645 block = &pem.Block{ 646 Type: "SYMMETRIC KEY", 647 Bytes: key, 648 } 649 } 650 if err != nil { 651 return nil, err 652 } 653 return pem.EncodeToMemory(block), nil 654 } 655 656 // WriteKeyToPemFile 将对称加密密钥写入pem文件 657 func WriteKeyToPemFile(FileName string, key []byte, pwd []byte) error { 658 pemBytes, err := WriteKeyToPem(key, pwd) 659 if err != nil { 660 return err 661 } 662 err = ioutil.WriteFile(FileName, pemBytes, 0666) 663 if err != nil { 664 return err 665 } 666 return nil 667 } 668 669 // 对称加密密钥与pem相互转换 670 // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑