forked from privacybydesign/irmago
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtimestamp.go
More file actions
108 lines (98 loc) · 3.23 KB
/
timestamp.go
File metadata and controls
108 lines (98 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package irma
import (
"crypto/sha256"
"encoding/asn1"
"errors"
gobig "math/big"
"github.com/bwesterb/go-atum"
"github.com/privacybydesign/gabi"
"github.com/privacybydesign/gabi/big"
)
// GetTimestamp GETs a signed timestamp (a signature over the current time and the parameters)
// over the message to be signed, the randomized signatures over the attributes, and the disclosed
// attributes, for in attribute-based signature sessions.
func GetTimestamp(message string, sigs []*big.Int, disclosed [][]*big.Int) (*atum.Timestamp, error) {
nonce, err := TimestampRequest(message, sigs, disclosed)
if err != nil {
return nil, err
}
alg := atum.Ed25519
return atum.SendRequest(TimestampServerURL, atum.Request{
Nonce: nonce,
PreferredSigAlg: &alg,
})
}
// TimestampRequest computes the nonce to be signed by a timestamp server, given a message to be signed
// in an attribute-based signature session along with the randomized signatures over the attributes
// and the disclosed attributes.
func TimestampRequest(message string, sigs []*big.Int, disclosed [][]*big.Int) ([]byte, error) {
msgHash := sha256.Sum256([]byte(message))
// Convert the sigs and disclosed (double) slices to (double) slices of gobig.Int's for asn1
sigsint := make([]*gobig.Int, len(sigs))
disclosedint := make([][]*gobig.Int, len(disclosed))
for i, k := range sigs {
sigsint[i] = k.Value()
}
for i, _ := range disclosed {
disclosedint[i] = make([]*gobig.Int, len(disclosed[i]))
for j, k := range disclosed[i] {
disclosedint[i][j] = k.Value()
}
}
bts, err := asn1.Marshal(struct {
Sigs []*gobig.Int
MsgHash []byte
Disclosed [][]*gobig.Int
}{
sigsint, msgHash[:], disclosedint,
})
if err != nil {
return nil, err
}
hashed := sha256.Sum256(bts)
return hashed[:], nil
}
const TimestampServerURL = "https://metrics.privacybydesign.foundation/atum"
// Given an SignedMessage, verify the timestamp over the signed message, disclosed attributes,
// and rerandomized CL-signatures.
func (sm *SignedMessage) VerifyTimestamp(message string, conf *Configuration) error {
if sm.Timestamp.ServerUrl != TimestampServerURL {
return errors.New("Untrusted timestamp server")
}
// Extract the disclosed attributes and randomized CL-signatures from the proofs in order to
// construct the nonce that should be signed by the timestamp server.
zero := big.NewInt(0)
size := len(sm.Signature)
sigs := make([]*big.Int, size)
disclosed := make([][]*big.Int, size)
for i, proof := range sm.Signature {
proofd := proof.(*gabi.ProofD)
sigs[i] = proofd.A
ct := MetadataFromInt(proofd.ADisclosed[1], conf).CredentialType()
if ct == nil {
return errors.New("Cannot verify timestamp: signature contains attributes from unknown credential type")
}
attrcount := len(ct.AttributeTypes) + 2 // plus secret key and metadata
disclosed[i] = make([]*big.Int, attrcount)
for j := 0; j < attrcount; j++ {
val, ok := proofd.ADisclosed[j]
if !ok {
disclosed[i][j] = zero
} else {
disclosed[i][j] = val
}
}
}
bts, err := TimestampRequest(message, sigs, disclosed)
if err != nil {
return err
}
valid, err := sm.Timestamp.Verify(bts)
if err != nil {
return err
}
if !valid {
return errors.New("Timestamp signature invalid")
}
return nil
}