gitee.com/zhaochuninhefei/gmgo@v0.0.31-0.20240209061119-069254a02979/sm4soft/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 /* 10 sm4soft 是sm4的纯软实现,基于tjfoc国密算法库`tjfoc/gmsm`做了少量修改。 11 对应版权声明: thrid_licenses/github.com/tjfoc/gmsm/版权声明 12 */ 13 14 package sm4soft 15 16 import ( 17 "crypto/rand" 18 "encoding/pem" 19 "errors" 20 "io/ioutil" 21 22 gmx509 "gitee.com/zhaochuninhefei/gmgo/x509" 23 ) 24 25 // ReadKeyFromPem will return SM4Key from PEM format data. 26 func ReadKeyFromPem(data []byte, pwd []byte) (SM4Key, error) { 27 block, _ := pem.Decode(data) 28 if block == nil { 29 return nil, errors.New("SM4: pem decode failed") 30 } 31 if gmx509.IsEncryptedPEMBlock(block) { 32 if block.Type != "SM4 ENCRYPTED KEY" { 33 return nil, errors.New("SM4: unknown type") 34 } 35 if len(pwd) == 0 { 36 return nil, errors.New("SM4: need passwd") 37 } 38 data, err := gmx509.DecryptPEMBlock(block, pwd) 39 if err != nil { 40 return nil, err 41 } 42 return data, nil 43 } 44 if block.Type != "SM4 KEY" { 45 return nil, errors.New("SM4: unknown type") 46 } 47 return block.Bytes, nil 48 } 49 50 // ReadKeyFromPemFile will return SM4Key from filename that saved PEM format data. 51 func ReadKeyFromPemFile(FileName string, pwd []byte) (SM4Key, error) { 52 data, err := ioutil.ReadFile(FileName) 53 if err != nil { 54 return nil, err 55 } 56 return ReadKeyFromPem(data, pwd) 57 } 58 59 // WriteKeyToPem will convert SM4Key to PEM format data and return it. 60 //goland:noinspection GoUnusedExportedFunction 61 func WriteKeyToPem(key SM4Key, pwd []byte) ([]byte, error) { 62 if pwd != nil { 63 block, err := gmx509.EncryptPEMBlock(rand.Reader, 64 "SM4 ENCRYPTED KEY", key, pwd, gmx509.PEMCipherAES256) //Use AES256 algorithms to encrypt SM4KEY 65 if err != nil { 66 return nil, err 67 } 68 return pem.EncodeToMemory(block), nil 69 } else { 70 block := &pem.Block{ 71 Type: "SM4 KEY", 72 Bytes: key, 73 } 74 return pem.EncodeToMemory(block), nil 75 } 76 } 77 78 // WriteKeyToPemFile will convert SM4Key to PEM format data, then write it 79 // into the input filename. 80 func WriteKeyToPemFile(FileName string, key SM4Key, pwd []byte) error { 81 var block *pem.Block 82 var err error 83 if pwd != nil { 84 block, err = gmx509.EncryptPEMBlock(rand.Reader, 85 "SM4 ENCRYPTED KEY", key, pwd, gmx509.PEMCipherAES256) 86 if err != nil { 87 return err 88 } 89 } else { 90 block = &pem.Block{ 91 Type: "SM4 KEY", 92 Bytes: key, 93 } 94 } 95 pemBytes := pem.EncodeToMemory(block) 96 err = ioutil.WriteFile(FileName, pemBytes, 0666) 97 if err != nil { 98 return err 99 } 100 return nil 101 } 102 103 // WriteKeytoMem sm4密钥转为pem字节数组 104 //goland:noinspection GoUnusedExportedFunction 105 func WriteKeytoMem(key SM4Key, pwd []byte) ([]byte, error) { 106 if pwd != nil { 107 block, err := gmx509.EncryptPEMBlock(rand.Reader, 108 "SM4 ENCRYPTED KEY", key, pwd, gmx509.PEMCipherAES256) 109 if err != nil { 110 return nil, err 111 } 112 return pem.EncodeToMemory(block), nil 113 } else { 114 block := &pem.Block{ 115 Type: "SM4 KEY", 116 Bytes: key, 117 } 118 return pem.EncodeToMemory(block), nil 119 } 120 } 121 122 // ReadKeyFromMem 将pem字节数组转为sm4密钥 123 //goland:noinspection GoUnusedExportedFunction 124 func ReadKeyFromMem(data []byte, pwd []byte) (SM4Key, error) { 125 block, _ := pem.Decode(data) 126 if gmx509.IsEncryptedPEMBlock(block) { 127 if block.Type != "SM4 ENCRYPTED KEY" { 128 return nil, errors.New("SM4: unknown type") 129 } 130 if len(pwd) == 0 { 131 return nil, errors.New("SM4: need passwd") 132 } 133 data, err := gmx509.DecryptPEMBlock(block, pwd) 134 if err != nil { 135 return nil, err 136 } 137 return data, nil 138 } 139 if block.Type != "SM4 KEY" { 140 return nil, errors.New("SM4: unknown type") 141 } 142 return block.Bytes, nil 143 }