/// /// Copyright (c) 2018 xdx. All rights reserved. /// /// \file: enc_impl.go /// /// \brief: sm9加密辅助函数 /// /// \author: xdx /// package sm9 import ( "bytes" "io" "math/big" "xdx.jelly/xgcl/gerrors" "xdx.jelly/xgcl/sm/sm4" "xdx.jelly/xgcl/sm/sm9/errors" ) type encReader struct { E encoder R io.Reader } func (er *encReader) Read(dst []byte) (n int, err error) { n, err = er.R.Read(dst) if err != nil { return } dst, err = er.E.encode(dst, dst) return len(dst), nil } type encoder interface { encode(dst, src []byte) ([]byte, error) } type encFunc func(dst, iv, key, src []byte) ([]byte, error) type worker struct { key []byte iv []byte f encFunc } func (o *worker) encode(dst, src []byte) ([]byte, error) { return o.f(dst, o.iv, o.key, src) } func DecryptParams(c *Cipher) (int, func(dst, iv, key, src []byte) ([]byte, error), error) { switch c.EncType { case EncTypeKDF: return len(c.C) + macKeySize, xor, nil case EncTypeSM4ECB: return sm4.BlockSize + macKeySize, decEcb, nil case EncTypeSM4CBC: return sm4.BlockSize + macKeySize, decCbc, nil case EncTypeSM4CFB: return sm4.BlockSize + macKeySize, decCfb, nil case EncTypeSM4OFB: return sm4.BlockSize + macKeySize, decOfb, nil default: return 0, nil, errors.ErrEncUnsupportedMode } } var DecryptFunc = map[EncType]func(dst, iv, key, src []byte) ([]byte, error){ EncTypeKDF: xor, EncTypeSM4ECB: decEcb, EncTypeSM4CBC: decCbc, EncTypeSM4CFB: decCfb, EncTypeSM4OFB: decOfb, } func xor(dst, iv, key, src []byte) ([]byte, error) { for i := range src { dst[i] = key[i] ^ src[i] } return dst, nil } func encEcb(dst, iv, key, src []byte) ([]byte, error) { return sm4.ECBEncrypt(dst, key, src) } func decEcb(dst, iv, key, src []byte) ([]byte, error) { return sm4.ECBDecrypt(dst, key, src) } func encCbc(dst, iv, key, src []byte) ([]byte, error) { return sm4.CBCEncrypt(dst, iv, key, src) } func decCbc(dst, iv, key, src []byte) ([]byte, error) { return sm4.CBCDecrypt(dst, iv, key, src) } func encCfb(dst, iv, key, src []byte) ([]byte, error) { return sm4.CFBEncrypt(dst, iv, key, src) } func decCfb(dst, iv, key, src []byte) ([]byte, error) { return sm4.CFBDecrypt(dst, iv, key, src) } func encOfb(dst, iv, key, src []byte) ([]byte, error) { return sm4.OFBEncrypt(dst, iv, key, src) } func decOfb(dst, iv, key, src []byte) ([]byte, error) { return sm4.OFBDecrypt(dst, iv, key, src) } // assume plain is padding and n blocks, iv is set of 16 bytes if cbc func encryption(id, plain []byte, pube *MastEncPublicKey, iv, rnd []byte, keylen int, f encFunc, encType EncType) *Cipher { c := new(Cipher) c.C = make([]byte, len(plain)) r := new(big.Int).SetBytes(rnd) // c.X, c.Y = genKeyPackage(id, pube, rnd) c.C1.Set(hashToG1(id, &pube.G1, hidEncryption)) c.C1.ScalarMult(&c.C1, r) c.EncType = encType copy(c.IV[:], iv) key := make([]byte, keylen) // genKey(key, id, &c.C1, &pube.G1, g2Gen, r) w := >{} if pube.e != nil { w.ScalarMult(pube.e, r) } else { pairing(w, &pube.G1, g2Gen) w.ScalarMult(w, r) } genKey(key, id, &c.C1, w) reader := &encReader{ E: &worker{key[:len(key)-macKeySize], iv, f}, R: bytes.NewReader(plain), } _, _ = reader.Read(c.C) copy(c.H[:], mac(key[len(key)-macKeySize:], c.C)) return c } // decryptions, encType are not used func decryption(id []byte, c *Cipher, de *UserEncKey, keylen int, f encFunc) ([]byte, error) { if !c.C1.IsValid() { return nil, gerrors.WithAnnotating(errors.ErrDecFailed, "C1 is not a valid point on curve") } w := >{} pairing(w, &c.C1, &de.G2) key := make([]byte, keylen) genKey(key, id, &c.C1, w) return decodeCipher(c, key, f) } // DecodeCipher export decodeCipher for tpc package. // Do not use this function unless you know what you are doing. var DecodeCipher = decodeCipher func decodeCipher(c *Cipher, key []byte, f encFunc) ([]byte, error) { keylen := len(key) m := mac(key[keylen-macKeySize:], c.C) if !bytes.Equal(c.H[:], m[:]) { return nil, gerrors.WithAnnotating(errors.ErrDecFailed, "check C3 failed") } reader := &encReader{ E: &worker{key[:keylen-macKeySize], c.IV[:], f}, R: bytes.NewReader(c.C), } plain := make([]byte, len(c.C)) _, _ = reader.Read(plain) return plain, nil }