gitee.com/lh-her-team/common@v1.5.1/crypto/hibe/hibe_noamd64/hibe.go (about)

     1  package hibe_noamd64
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/base64"
     6  	"errors"
     7  	"fmt"
     8  	"strings"
     9  
    10  	"gitee.com/lh-her-team/common/crypto"
    11  	"gitee.com/lh-her-team/common/crypto/hibe/hibe_noamd64/hibe"
    12  	"gitee.com/lh-her-team/common/crypto/hibe/hibe_noamd64/hibe/bn256"
    13  )
    14  
    15  const (
    16  	// hibe message's cipher text key
    17  	hibeMsgCipherTextKey = "CT"
    18  )
    19  
    20  var ErrUnsupported = errors.New("hibe: unsupported")
    21  
    22  // EncryptHibeMsg is used to encrypt plainText by receiverIds and their paramsList
    23  // plaintext: plain text bytes
    24  // receiverIds: message receivers' id list, using "/" to separate hierarchy identity in each id string
    25  // paramsList: HIBE parameters list of the message receiver, len(paramsList) should be equal to len(receiverIds),
    26  //   paramsList[i] are the HIBE parameters of receiverIds[i]
    27  // symKeyType: symmetric key type (aes or sm4), used to symmetric encrypt the plain text first
    28  func EncryptHibeMsg(plaintext []byte, receiverIds []string, paramsList []*hibe.Params,
    29  	symKeyType crypto.KeyType) (map[string]string, error) {
    30  	// input parameter validation
    31  	if len(plaintext) == 0 {
    32  		return nil, errors.New("invalid parameters, plaintext is nil")
    33  	}
    34  	if len(receiverIds) == 0 {
    35  		return nil, errors.New("invalid parameters, receiverIds is nil")
    36  	}
    37  	for _, id := range receiverIds {
    38  		if err := ValidateId(id); err != nil {
    39  			return nil, err
    40  		}
    41  	}
    42  	if len(paramsList) == 0 {
    43  		return nil, errors.New("invalid parameters, paramsList is nil")
    44  	}
    45  	if len(receiverIds) != len(paramsList) {
    46  		return nil, errors.New("invalid parameters, receiverIds and paramsList do not match, place check them")
    47  	}
    48  	if symKeyType != crypto.AES && symKeyType != crypto.SM4 {
    49  		return nil, fmt.Errorf("invalid parameters, unsupported symmetric encryption algorithm type : %d", symKeyType)
    50  	}
    51  	// generate symmetric encryption (like AES, SM4) Key
    52  	// generate a random point from GT
    53  	_, randG1, err := bn256.RandomG1(rand.Reader)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  	_, randG2, err := bn256.RandomG2(rand.Reader)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  	gt := bn256.Pair(randG1, randG2)
    62  	gtBytes := gt.Marshal()
    63  	symKey, err := generateSymKeyFromGtBytes(gtBytes, symKeyType)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  	// use sym key to encrypt plaintext
    68  	encryptedMessage, err := symKey.Encrypt(plaintext)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	encryptedMessageStr := base64.StdEncoding.EncodeToString(encryptedMessage)
    73  	// Remove redundant data (Id)
    74  	// Only the lowest level ID is reserved
    75  	refinedReceiverIds, refinedParamsList, err := refineIdsAndParams(receiverIds, paramsList)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	hibeIds := idStrList2HibeIds(refinedReceiverIds)
    80  	// ciphertext []byte -> string
    81  	ciphertextsStr := make([]string, len(refinedReceiverIds))
    82  	for i, id := range hibeIds {
    83  		ciphertext, err := hibe.Encrypt(rand.Reader, refinedParamsList[i], id[:], gt)
    84  		if err != nil {
    85  			return nil, err
    86  		}
    87  		ciphertextsStr[i] = base64.StdEncoding.EncodeToString(ciphertext.Marshal())
    88  	}
    89  	hibeMsgMap := make(map[string]string)
    90  	hibeMsgMap[hibeMsgCipherTextKey] = encryptedMessageStr
    91  	for i, ciphertextStr := range ciphertextsStr {
    92  		hibeMsgMap[refinedReceiverIds[i]] = ciphertextStr
    93  	}
    94  	return hibeMsgMap, nil
    95  }
    96  
    97  // DecryptHibeMsg is used to decrypt the HIBE message constructed by EncryptHibeMsg
    98  // localId: hibe Id
    99  // hibeParams: HIBE parameters of the HIBE system to which ID belongs
   100  // prvKey: the localId's hibe private Key
   101  // hibeMsgMap: HIBE message encrypt by EncryptHibeMsg
   102  // symKeyType: symmetric key type (aes or sm4), used to symmetric encrypt the plain text first
   103  func DecryptHibeMsg(localId string, hibeParams *hibe.Params, prvKey *hibe.PrivateKey,
   104  	hibeMsgMap map[string]string, symKeyType crypto.KeyType) ([]byte, error) {
   105  	// input parameter validation
   106  	if err := ValidateId(localId); err != nil {
   107  		return nil, err
   108  	}
   109  	if hibeParams == nil {
   110  		return nil, errors.New("invalid parameters, hibeParams is nil")
   111  	}
   112  	if prvKey == nil {
   113  		return nil, errors.New("invalid parameters, prvKey is nil")
   114  	}
   115  	if hibeMsgMap == nil {
   116  		return nil, errors.New("invalid parameters, hibeMsgMap is nil")
   117  	}
   118  	if symKeyType != crypto.AES && symKeyType != crypto.SM4 {
   119  		return nil, fmt.Errorf("invalid parameters, unsupported symmetric encryption algorithm type : %d", symKeyType)
   120  	}
   121  	matchedId := ""
   122  	for id := range hibeMsgMap {
   123  		if id == hibeMsgCipherTextKey {
   124  			continue
   125  		}
   126  		if strings.HasPrefix(id, localId) {
   127  			matchedId = id
   128  			break
   129  		}
   130  	}
   131  	if matchedId == "" {
   132  		return nil, errors.New("no permission")
   133  	}
   134  	matchedPrvKey := new(hibe.PrivateKey)
   135  	if matchedId != localId {
   136  		matchedIdStr, hibeIds := IdStr2HibeId(matchedId)
   137  		localIdStrLen := len(strings.Split(localId, "/"))
   138  		var err error
   139  		for i := localIdStrLen + 1; i <= len(matchedIdStr); i++ {
   140  			prvKey, err = hibe.KeyGenFromParent(rand.Reader, hibeParams, prvKey, hibeIds[:i])
   141  			if err != nil {
   142  				return nil, err
   143  			}
   144  		}
   145  		matchedPrvKey = prvKey
   146  	}
   147  	matchedPrvKey = prvKey
   148  	// get Gt
   149  	encryptGt := &hibe.Ciphertext{}
   150  	encryptGtBytes, err := base64.StdEncoding.DecodeString(hibeMsgMap[matchedId])
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  	if encryptGtBytes == nil {
   155  		return nil, errors.New("no permission")
   156  	}
   157  	encryptGt, ok := encryptGt.Unmarshal(encryptGtBytes)
   158  	if !ok {
   159  		return nil, errors.New("encryptGt.Unmarshal failed, please check it")
   160  	}
   161  	// get GT
   162  	gt := hibe.Decrypt(matchedPrvKey, encryptGt)
   163  	// generate symmetric encryption (like AES, SM4) Key
   164  	// generate a random point from GT
   165  	gtBytes := gt.Marshal()
   166  	symKey, err := generateSymKeyFromGtBytes(gtBytes, symKeyType)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  	// decrypt messageBytes
   171  	// encryptedMessage -> []byte
   172  	encryptedMessageBytes, err := base64.StdEncoding.DecodeString(hibeMsgMap[hibeMsgCipherTextKey])
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  	// use sym key to encrypt plaintext
   177  	message, err := symKey.Decrypt(encryptedMessageBytes)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  	return message, nil
   182  }