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  }