qsign

package module
v1.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 1, 2019 License: MIT Imports: 9 Imported by: 5

README

Qsign

Build Status Go Report Card codecov

Generate signature for Golang struct value.

Requirements

  • Go version >= 1.8

Signing Method

It uses the signing method widely used by tencent and wechat APIs.

For example, we have such data to be signed:

appid: wxd930ea5d5a258f4f
mch_id: 10000100
device_info: 1000
body: test
nonce_str: ibuaiVcKdpRxkhJA

First step, we make a query string using the data. Key is sorted by ASCII order. Then we have string A.

A := "appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA"

Next, we prepend or append some secret data to A. Then we have our digest B. Here, we append a secret key.

B := A + "&key=192006250b4c09247ec02edce69f6a2d"
// appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA&key=192006250b4c09247ec02edce69f6a2d

Finaly, calculate the checksum of the digest using some hash method. Then we get the signature.

md5(B)

Usage

Qsign implements the signing method mentioned before. It uses reflection to get structs' fields, determines which fields will appear in the digest. By default field name is used as key. You can asign a "qsign" tag to that field to change key string or ignore that field. Qsign also support "json", "yaml", "xml" and "form" tags optionally.

Tag "qsign" has the highest priority. A field with tag qsign:"-" will be ignored.

data := struct {
	AppId      string `qsign:"appid"`
	MchId      int    `qsign:"mch_id"`
	DeviceInfo string `qsign:"device_info"`
	Body       string `qsign:"body"`
	NonceStr   string `qsign:"nonce_str"`
	IgnoreMe   string `qsign:"-"`
}{
	AppId:      "wxd930ea5d5a258f4f",
	MchId:      10000100,
	DeviceInfo: "1000",
	Body:       "test",
	NonceStr:   "ibuaiVcKdpRxkhJA",
	IgnoreMe:   "won't be used to generate digest",
}

q := qsign.NewQsign(qsign.Options{
	SuffixGenerator: func() string {
		return "&key=192006250b4c09247ec02edce69f6a2d"
	},
})

// digest, _ := q.Digest(data)
// fmt.Printf("%s\n", string(digest))
// appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA&key=192006250b4c09247ec02edce69f6a2d

signature, _ := q.Sign(data)
fmt.Printf("%s\n", string(signature))
// 9a0a8659f005d6984697e2ca0a9cf3b7

Limitations

Array and Slice types of field are not supported.

But if a field type implements the Marshaler, Qsgin will use the result of function MarshalQsgin() string as value in the digest. Note, for using this feature, either the field or the struct must be addressable. For example:

type MyType struct {
	Key   string
	Value string
}

func (m *MyType) MarshalQsign() string {
	return fmt.Sprintf("%s->%s", m.Key, m.Value)
}

func main() {
	data := &struct {
		T MyType `qsign:"t"`
	}{
		T: MyType{"jerray", "qsign"},
	}

	q := qsign.NewQsign(qsign.Options{})

	digest, _ := q.Digest(data)
	fmt.Printf("%s\n", string(digest))
	// t=jerray->qsign
}

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Encoder

type Encoder func() Encoding

Encoder is a function returns Encoding interface for Qsign to encode digest.

type Encoding

type Encoding interface {

	// Encode encodes src using the encoding enc, writing EncodedLen(len(src)) bytes to dst.
	Encode(dst, src []byte)

	// EncodedLen returns the length in bytes of the encoding scheme of an input buffer of length n.
	EncodedLen(n int) int
}

Encoding is an interface for various encoding scheme.

type Filter

type Filter func(key, value string) bool

Filter is function receives a key-value pair, returns bool value. It's used to filter out invalid key-value pair in the digest.

type Generator

type Generator func() string

Generator is function returns string. It's used to generate digest prefix or suffix.

type Hasher

type Hasher func() hash.Hash

Hasher is function returns hash.Hash. By default, Qsign uses md5 hash. You can provide your own hash interface instead.

type Marshaler added in v1.2.0

type Marshaler interface {
	MarshalQsign() string
}

type Options

type Options struct {
	PrefixGenerator Generator
	SuffixGenerator Generator
	Encoder         Encoder
	Filter          Filter
	Hasher          Hasher
}

Options is optional attributes for building NewSign function to build *Qsign.

PrefixGenerator and SuffixGenerator is two functions which you can use to generating prefix string prepending to digest and suffix string appending to digest string.

Filter is a function used to get rid of some keys or values. For example you want a field which its value is empty being ignored. And this is the default filter.

Encoder is a function which returns Encoding interface. By default it returns hex encoding. If you want to use base64 encoding, you can give a function which returns base64.StdEncoding.

Hasher is a function which returns hash.Hash. By default it returns the Hash from crypto/md5.

type Qsign

type Qsign struct {
	// contains filtered or unexported fields
}

Qsign is the signer which signs structs.

func NewQsign

func NewQsign(options Options) *Qsign

NewQsign returns a new *Qsign computing signature.

func (*Qsign) Digest

func (q *Qsign) Digest(v interface{}) ([]byte, error)

Digest generates digest bytes for interface v. By default, it parses struct v, gets all the keys and values, and connects them like an HTTP query string.

Key's value is struct field name if there is no tags like "qsign", "json", "yaml" or "xml". If any key has a tag mentioned before, it will get value from the tag for that key. Tag name "qsign" has the highest priority. Field tag valuewith "-" will be ignored.

All the values expect for Array, Slice and Struct type will be parsed to string. There is an exception here, if the struct has a String method (`func String() string`), it will be parsed.

func (*Qsign) SetConnector

func (q *Qsign) SetConnector(s string)

SetConnector changes the default connector.

func (*Qsign) SetDelimiter

func (q *Qsign) SetDelimiter(s string)

SetDelimiter changes the default delimiter.

func (*Qsign) Sign

func (q *Qsign) Sign(v interface{}) ([]byte, error)

Sign returns signature bytes for interface v. It calculate the digest of input struct first. And then gets checksum of the digest using hasher. Finally encodes the checksum and returns.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL