-
Notifications
You must be signed in to change notification settings - Fork 136
/
bls.go
115 lines (99 loc) · 3.56 KB
/
bls.go
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
109
110
111
112
113
114
115
//go:build cgo
// +build cgo
package ffi
// #cgo linux LDFLAGS: ${SRCDIR}/libfilcrypto.a -Wl,-unresolved-symbols=ignore-all
// #cgo darwin LDFLAGS: ${SRCDIR}/libfilcrypto.a -Wl,-undefined,dynamic_lookup
// #cgo pkg-config: ${SRCDIR}/filcrypto.pc
// #include "./filcrypto.h"
import "C"
import (
"github.com/filecoin-project/filecoin-ffi/cgo"
)
// Hash computes the digest of a message
func Hash(message Message) Digest {
digest := cgo.Hash(cgo.AsSliceRefUint8(message))
if digest == nil {
return Digest{}
}
return *digest
}
// Verify verifies that a signature is the aggregated signature of digests - pubkeys
func Verify(signature *Signature, digests []Digest, publicKeys []PublicKey) bool {
// prep data
flattenedDigests := make([]byte, DigestBytes*len(digests))
for idx, digest := range digests {
copy(flattenedDigests[(DigestBytes*idx):(DigestBytes*(1+idx))], digest[:])
}
flattenedPublicKeys := make([]byte, PublicKeyBytes*len(publicKeys))
for idx, publicKey := range publicKeys {
copy(flattenedPublicKeys[(PublicKeyBytes*idx):(PublicKeyBytes*(1+idx))], publicKey[:])
}
return cgo.Verify(
cgo.AsSliceRefUint8(signature[:]),
cgo.AsSliceRefUint8(flattenedDigests),
cgo.AsSliceRefUint8(flattenedPublicKeys),
)
}
// HashVerify verifies that a signature is the aggregated signature of hashed messages.
func HashVerify(signature *Signature, messages []Message, publicKeys []PublicKey) bool {
var flattenedMessages []byte
messagesSizes := make([]uint, len(messages))
for idx := range messages {
flattenedMessages = append(flattenedMessages, messages[idx]...)
messagesSizes[idx] = uint(len(messages[idx]))
}
flattenedPublicKeys := make([]byte, PublicKeyBytes*len(publicKeys))
for idx, publicKey := range publicKeys {
copy(flattenedPublicKeys[(PublicKeyBytes*idx):(PublicKeyBytes*(1+idx))], publicKey[:])
}
return cgo.HashVerify(
cgo.AsSliceRefUint8(signature[:]),
cgo.AsSliceRefUint8(flattenedMessages),
cgo.AsSliceRefUint(messagesSizes),
cgo.AsSliceRefUint8(flattenedPublicKeys),
)
}
// Aggregate aggregates signatures together into a new signature. If the
// provided signatures cannot be aggregated (due to invalid input or an
// an operational error), Aggregate will return nil.
func Aggregate(signatures []Signature) *Signature {
// prep data
flattenedSignatures := make([]byte, SignatureBytes*len(signatures))
for idx, sig := range signatures {
copy(flattenedSignatures[(SignatureBytes*idx):(SignatureBytes*(1+idx))], sig[:])
}
return cgo.Aggregate(cgo.AsSliceRefUint8(flattenedSignatures))
}
// PrivateKeyGenerate generates a private key
func PrivateKeyGenerate() PrivateKey {
key := cgo.PrivateKeyGenerate()
if key == nil {
return PrivateKey{}
}
return *key
}
// PrivateKeyGenerate generates a private key in a predictable manner.
func PrivateKeyGenerateWithSeed(seed PrivateKeyGenSeed) PrivateKey {
ary := cgo.AsByteArray32(seed[:])
key := cgo.PrivateKeyGenerateWithSeed(&ary)
if key == nil {
return PrivateKey{}
}
return *key
}
// PrivateKeySign signs a message
func PrivateKeySign(privateKey PrivateKey, message Message) *Signature {
return cgo.PrivateKeySign(cgo.AsSliceRefUint8(privateKey[:]), cgo.AsSliceRefUint8(message))
}
// PrivateKeyPublicKey gets the public key for a private key
func PrivateKeyPublicKey(privateKey PrivateKey) *PublicKey {
return cgo.PrivateKeyPublicKey(cgo.AsSliceRefUint8(privateKey[:]))
}
// CreateZeroSignature creates a zero signature, used as placeholder in filecoin.
func CreateZeroSignature() Signature {
signature := cgo.CreateZeroSignature()
if signature == nil {
return Signature{}
}
return *signature
}