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