github.com/emmansun/gmsm@v0.29.1/pkcs/pkcs5_pbes1.go (about) 1 package pkcs 2 3 import ( 4 "crypto/cipher" 5 "crypto/des" 6 "crypto/md5" 7 "crypto/sha1" 8 "crypto/x509/pkix" 9 "encoding/asn1" 10 "errors" 11 "hash" 12 "io" 13 14 "github.com/emmansun/gmsm/pkcs/internal/md2" 15 "github.com/emmansun/gmsm/pkcs/internal/rc2" 16 ) 17 18 var ( 19 pbeWithMD2AndDESCBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 1} 20 pbeWithMD2AndRC2CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 4} 21 pbeWithMD5AndDESCBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 3} 22 pbeWithMD5AndRC2CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 6} 23 pbeWithSHA1AndDESCBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 10} 24 pbeWithSHA1AndRC2CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 11} 25 ) 26 27 type pbeParameter struct { 28 Salt []byte 29 Iteration int 30 } 31 32 // PBES1 implements the Password-Based Encryption Scheme 1. 33 type PBES1 struct { 34 Algorithm pkix.AlgorithmIdentifier 35 } 36 37 // newPBES1 creates a new PBES1 instance. 38 func newPBES1(rand io.Reader, oid asn1.ObjectIdentifier, saltLen, iterations int) (*PBES1, error) { 39 salt := make([]byte, saltLen) 40 if _, err := rand.Read(salt); err != nil { 41 return nil, err 42 } 43 param := pbeParameter{Salt: salt, Iteration: iterations} 44 marshalledParams, err := asn1.Marshal(param) 45 if err != nil { 46 return nil, err 47 } 48 return &PBES1{ 49 Algorithm: pkix.AlgorithmIdentifier{ 50 Algorithm: oid, 51 Parameters: asn1.RawValue{FullBytes: marshalledParams}, 52 }, 53 }, nil 54 } 55 56 func NewPbeWithMD2AndDESCBC(rand io.Reader, saltLen, iterations int) (*PBES1, error) { 57 return newPBES1(rand, pbeWithMD2AndDESCBC, saltLen, iterations) 58 } 59 60 func NewPbeWithMD2AndRC2CBC(rand io.Reader, saltLen, iterations int) (*PBES1, error) { 61 return newPBES1(rand, pbeWithMD2AndRC2CBC, saltLen, iterations) 62 } 63 64 func NewPbeWithMD5AndDESCBC(rand io.Reader, saltLen, iterations int) (*PBES1, error) { 65 return newPBES1(rand, pbeWithMD5AndDESCBC, saltLen, iterations) 66 } 67 68 func NewPbeWithMD5AndRC2CBC(rand io.Reader, saltLen, iterations int) (*PBES1, error) { 69 return newPBES1(rand, pbeWithMD5AndRC2CBC, saltLen, iterations) 70 } 71 72 func NewPbeWithSHA1AndDESCBC(rand io.Reader, saltLen, iterations int) (*PBES1, error) { 73 return newPBES1(rand, pbeWithSHA1AndDESCBC, saltLen, iterations) 74 } 75 76 func NewPbeWithSHA1AndRC2CBC(rand io.Reader, saltLen, iterations int) (*PBES1, error) { 77 return newPBES1(rand, pbeWithSHA1AndRC2CBC, saltLen, iterations) 78 } 79 80 // Key returns the key derived from the password according PBKDF1. 81 func (pbes1 *PBES1) key(password []byte) ([]byte, error) { 82 param := new(pbeParameter) 83 if _, err := asn1.Unmarshal(pbes1.Algorithm.Parameters.FullBytes, param); err != nil { 84 return nil, err 85 } 86 var hash hash.Hash 87 switch { 88 case pbes1.Algorithm.Algorithm.Equal(pbeWithMD2AndDESCBC) || pbes1.Algorithm.Algorithm.Equal(pbeWithMD2AndRC2CBC): 89 hash = md2.New() 90 case pbes1.Algorithm.Algorithm.Equal(pbeWithMD5AndDESCBC) || pbes1.Algorithm.Algorithm.Equal(pbeWithMD5AndRC2CBC): 91 hash = md5.New() 92 case pbes1.Algorithm.Algorithm.Equal(pbeWithSHA1AndDESCBC) || pbes1.Algorithm.Algorithm.Equal(pbeWithSHA1AndRC2CBC): 93 hash = sha1.New() 94 default: 95 return nil, errors.New("pbes: unsupported pbes1 cipher") 96 } 97 hash.Write(password) 98 hash.Write(param.Salt) 99 key := hash.Sum(nil) 100 for i := 1; i < param.Iteration; i++ { 101 hash.Reset() 102 hash.Write(key) 103 key = hash.Sum(key[:0]) 104 } 105 return key, nil 106 } 107 108 func (pbes1 *PBES1) newBlock(key []byte) (cipher.Block, error) { 109 var block cipher.Block 110 switch { 111 case pbes1.Algorithm.Algorithm.Equal(pbeWithMD2AndDESCBC) || 112 pbes1.Algorithm.Algorithm.Equal(pbeWithMD5AndDESCBC) || 113 pbes1.Algorithm.Algorithm.Equal(pbeWithSHA1AndDESCBC): 114 block, _ = des.NewCipher(key[:8]) 115 case pbes1.Algorithm.Algorithm.Equal(pbeWithMD2AndRC2CBC) || 116 pbes1.Algorithm.Algorithm.Equal(pbeWithMD5AndRC2CBC) || 117 pbes1.Algorithm.Algorithm.Equal(pbeWithSHA1AndRC2CBC): 118 block, _ = rc2.NewCipher(key[:8]) 119 default: 120 return nil, errors.New("pbes: unsupported pbes1 cipher") 121 } 122 return block, nil 123 } 124 125 func (pbes1 *PBES1) Encrypt(rand io.Reader, password, plaintext []byte) (*pkix.AlgorithmIdentifier, []byte, error) { 126 key, err := pbes1.key(password) 127 if err != nil { 128 return nil, nil, err 129 } 130 block, err := pbes1.newBlock(key) 131 if err != nil { 132 return nil, nil, err 133 } 134 ciphertext, err := cbcEncrypt(block, key[8:16], plaintext) 135 if err != nil { 136 return nil, nil, err 137 } 138 return &pbes1.Algorithm, ciphertext, nil 139 } 140 141 func (pbes1 *PBES1) Decrypt(password, ciphertext []byte) ([]byte, KDFParameters, error) { 142 key, err := pbes1.key(password) 143 if err != nil { 144 return nil, nil, err 145 } 146 block, err := pbes1.newBlock(key) 147 if err != nil { 148 return nil, nil, err 149 } 150 plaintext, err := cbcDecrypt(block, key[8:16], ciphertext) 151 if err != nil { 152 return nil, nil, ErrPBEDecryption 153 } 154 return plaintext, nil, nil 155 } 156 157 func IsPBES1(algorithm pkix.AlgorithmIdentifier) bool { 158 return algorithm.Algorithm.Equal(pbeWithMD2AndDESCBC) || 159 algorithm.Algorithm.Equal(pbeWithMD2AndRC2CBC) || 160 algorithm.Algorithm.Equal(pbeWithMD5AndDESCBC) || 161 algorithm.Algorithm.Equal(pbeWithMD5AndRC2CBC) || 162 algorithm.Algorithm.Equal(pbeWithSHA1AndDESCBC) || 163 algorithm.Algorithm.Equal(pbeWithSHA1AndRC2CBC) 164 }