irma_signature.go 1.59 KB
Newer Older
1
2
3
4
5
6
7
package irma

import (
	"crypto/sha256"
	"encoding/asn1"
	"log"
	"math/big"
8
9
10

	"github.com/bwesterb/go-atum"
	"github.com/mhe/gabi"
11
12
13
14
)

// IrmaSignedMessage is a message signed with an attribute-based signature
// The 'realnonce' will be calculated as: SigRequest.GetNonce() = ASN1(sha256(message), sha256(nonce))
15
// // TODO: remove pointer from Signature
16
17
18
19
20
type IrmaSignedMessage struct {
	Signature *gabi.ProofList `json:"signature"`
	Nonce     *big.Int        `json:"nonce"`
	Context   *big.Int        `json:"context"`
	Message   string          `json:"message"`
21
	Timestamp *atum.Timestamp `json:"timestamp"`
22
23
24
}

func (im *IrmaSignedMessage) GetNonce() *big.Int {
25
	return ASN1ConvertSignatureNonce(im.Message, im.Nonce, im.Timestamp)
26
27
28
}

func (im *IrmaSignedMessage) MatchesNonceAndContext(request *SignatureRequest) bool {
29
30
31
	return im.Nonce.Cmp(request.Nonce) == 0 &&
		im.Context.Cmp(request.Context) == 0 &&
		im.GetNonce().Cmp(request.GetNonce()) == 0
32
33
34
35
}

// Convert a Nonce to a nonce of a signature session
// (with the message already hashed into it).
36
37
38
39
40
41
42
43
44
func ASN1ConvertSignatureNonce(message string, nonce *big.Int, timestamp *atum.Timestamp) *big.Int {
	msgHash := sha256.Sum256([]byte(message))
	tohash := []interface{}{nonce, new(big.Int).SetBytes(msgHash[:])}
	if timestamp != nil {
		tohash = append(tohash, timestamp.Sig.Data)
	}
	// TODO remove the 2, or keep backwards compatible?
	tohash = append([]interface{}{big.NewInt(int64(len(tohash)))}, tohash...)
	asn1bytes, err := asn1.Marshal(tohash)
45
	if err != nil {
46
		log.Print(err) // TODO
47
48
49
50
	}
	asn1hash := sha256.Sum256(asn1bytes)
	return new(big.Int).SetBytes(asn1hash[:])
}