-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfidoAssertion.go
222 lines (171 loc) · 8.2 KB
/
fidoAssertion.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
package k6fido
import (
"encoding/base64"
"fmt"
"math/rand"
)
const tagAaid int16 = 0x2E0B
const tagAssertionInfo int16 = 0x2E0E
const tagFinalChallengeHash int16 = 0x2E0A
const tagKeyID int16 = 0x2E09
const tagCounters int16 = 0x2E0D
const tagPubKey int16 = 0x2E0C
const tagUafv1Krd int16 = 0x3E03
const tagSignature int16 = 0x2E06
const tagAttestationBasicSurrogate int16 = 0x3E08
const tagUafv1RegAssertion int16 = 0x3E01
const tagAuthenticatorNonce int16 = 0x2E0F
const tagUafv1AuthAssertion int16 = 0x3E02
const tagUafv1SignedData int16 = 0x3E04
const tagTransactionContextHash = 0x2E10
const algSignSecp256R1EcdsaSha256Der = 0x0002
const algKeyEccX962Der = 0x0101
const authModeUserVerified int8 = 1
const authModeTxnContentVerified = 2
const uafv1tlv string = "UAFV1TLV"
type AuthenticatorSignAssertion struct {
Assertion string `json:"assertion"`
AssertionScheme string `json:"assertionScheme"`
}
type SignedAssertionsBuilder interface {
Build(string, string) (*AuthenticatorSignAssertion, error)
}
type FidoRegistrationSignedAssertionsBuilder struct {
assertions *Assertions
}
type FidoAuthenticationSignedAssertionsBuilder struct {
assertions *Assertions
}
type Assertions struct {
aaid string
authenticatorVersion int16
signCounter int32
registrationCounter int32
publicKey []byte
authenticationMode int8
signatureAlgAndEncoding int16
publicKeyAlgAndEncoding int16
finalChallengeParamsHash []byte
transactionTextHash []byte
signatureSignedData string
overriddenSignature string
}
func NewFidoRegistrationSignedAssertions(aaid string, signatureSignedData string,
pubKeyBas64Encoded string, privKeyBase64Encoded string, overriddenSignature string, finalChallengeParamsHash []byte, keyId string) (*AuthenticatorSignAssertion, error) {
const authenticatorVersion int16 = 1
const signCounter int32 = 0
const registrationCounter int32 = 0
pubKeyBytes, _ := base64.StdEncoding.DecodeString(pubKeyBas64Encoded)
assertion := &Assertions{
aaid: aaid,
publicKey: pubKeyBytes,
authenticatorVersion: authenticatorVersion,
signCounter: signCounter,
registrationCounter: registrationCounter,
signatureAlgAndEncoding: algSignSecp256R1EcdsaSha256Der,
publicKeyAlgAndEncoding: algKeyEccX962Der,
overriddenSignature: overriddenSignature,
signatureSignedData: signatureSignedData,
finalChallengeParamsHash: finalChallengeParamsHash,
}
fidoRegistrationSignedAssertionsBuilder := FidoRegistrationSignedAssertionsBuilder{assertions: assertion}
return fidoRegistrationSignedAssertionsBuilder.Build(privKeyBase64Encoded, pubKeyBas64Encoded, keyId)
}
func NewFidoAuthenticationSignedAssertions(aaid string, pubKeyBas64Encoded string, privKeyBase64Encoded string, overriddenSignature string, signatureSignedData string, finalChallengeParamsHash []byte, keyId string) (*AuthenticatorSignAssertion, error) {
const authenticatorVersion int16 = 1
const signCounter int32 = 0
const registrationCounter int32 = 0
pubKeyBytes, _ := base64.StdEncoding.DecodeString(pubKeyBas64Encoded)
assertion := &Assertions{
aaid: aaid,
publicKey: pubKeyBytes,
authenticatorVersion: authenticatorVersion,
signCounter: signCounter,
registrationCounter: registrationCounter,
signatureAlgAndEncoding: algSignSecp256R1EcdsaSha256Der,
publicKeyAlgAndEncoding: algKeyEccX962Der,
overriddenSignature: overriddenSignature,
signatureSignedData: signatureSignedData,
authenticationMode: authModeUserVerified,
finalChallengeParamsHash: finalChallengeParamsHash,
}
fidoAuthenticationAssertionsBuilder := FidoAuthenticationSignedAssertionsBuilder{assertions: assertion}
return fidoAuthenticationAssertionsBuilder.Build(privKeyBase64Encoded, pubKeyBas64Encoded, keyId)
}
func (fra *FidoRegistrationSignedAssertionsBuilder) Build(privKeyStr string, pubKeyStr string, keyId string) (*AuthenticatorSignAssertion, error) {
tlvObjectAaid := NewFidoUafTlvObject(tagAaid, []byte(fra.assertions.aaid))
var assertionInfoContentLength = 2 + 1 + 2 + 2
tlvObjectAssertionInfo := NewFidoUafTlvObjectWithSize(tagAssertionInfo, int16(assertionInfoContentLength))
tlvObjectAssertionInfo.PutInt16(fra.assertions.authenticatorVersion)
tlvObjectAssertionInfo.PutInt8(fra.assertions.authenticationMode)
tlvObjectAssertionInfo.PutInt16(fra.assertions.signatureAlgAndEncoding)
tlvObjectAssertionInfo.PutInt16(fra.assertions.publicKeyAlgAndEncoding)
tlvFinalChallengeHash := NewFidoUafTlvObject(tagFinalChallengeHash, fra.assertions.finalChallengeParamsHash)
tlvObjectKeyId := NewFidoUafTlvObject(tagKeyID, []byte(keyId))
objectCountersContentLength := 4 + 4
tlvObjectCounters := NewFidoUafTlvObjectWithSize(tagCounters, int16(objectCountersContentLength))
tlvObjectCounters.PutInt32(fra.assertions.signCounter)
tlvObjectCounters.PutInt32(fra.assertions.registrationCounter)
tlvObjectPubKey := NewFidoUafTlvObject(tagPubKey, fra.assertions.publicKey)
tlvObjectKeyRegistrationData := NewFidoUafTlvObjectFromArray(tagUafv1Krd, []*FidoUafTlvObject{
tlvObjectAaid,
tlvObjectAssertionInfo,
tlvFinalChallengeHash,
tlvObjectKeyId,
tlvObjectCounters,
tlvObjectPubKey,
}...)
krdSignature, err := SignDataLocal(tlvObjectKeyRegistrationData.GetByteArray(), privKeyStr)
if err != nil {
return nil, fmt.Errorf("Error creating signature: %v", err)
}
tlvObjectSignature := NewFidoUafTlvObject(tagSignature, krdSignature)
tlvObjectAttestationBasicSurrogate := NewFidoUafTlvObjectFromArray(tagAttestationBasicSurrogate, tlvObjectSignature)
tlvObjectRegistrationAssertion := NewFidoUafTlvObjectFromArray(tagUafv1RegAssertion, tlvObjectKeyRegistrationData, tlvObjectAttestationBasicSurrogate)
assertionBytes := tlvObjectRegistrationAssertion.GetByteArray()
encoder := base64.URLEncoding.WithPadding(base64.NoPadding)
base64EncodedAssertion := encoder.EncodeToString(assertionBytes)
return &AuthenticatorSignAssertion{
Assertion: base64EncodedAssertion,
AssertionScheme: uafv1tlv,
}, nil
}
func (fra *FidoAuthenticationSignedAssertionsBuilder) Build(privKeyStr string, pubKeyStr string, keyId string) (*AuthenticatorSignAssertion, error) {
tlvObjectAaid := NewFidoUafTlvObject(tagAaid, []byte(fra.assertions.aaid))
var assertionInfoContentLength = 2 + 1 + 2
tlvObjectAssertionInfo := NewFidoUafTlvObjectWithSize(tagAssertionInfo, int16(assertionInfoContentLength))
tlvObjectAssertionInfo.PutInt16(fra.assertions.authenticatorVersion)
tlvObjectAssertionInfo.PutInt8(fra.assertions.authenticationMode)
tlvObjectAssertionInfo.PutInt16(fra.assertions.signatureAlgAndEncoding)
authenticatorNonce := make([]byte, 8)
rand.Read(authenticatorNonce)
tlvNonceObject := NewFidoUafTlvObject(tagAuthenticatorNonce, authenticatorNonce)
tlvFinalChallengeHash := NewFidoUafTlvObject(tagFinalChallengeHash, fra.assertions.finalChallengeParamsHash)
tlvTransactionContentHash := NewFidoUafTlvObject(tagTransactionContextHash, fra.assertions.transactionTextHash)
tlvObjectKeyId := NewFidoUafTlvObject(tagKeyID, []byte(keyId))
var objectCountersContentLength = 4
tlvObjectCounters := NewFidoUafTlvObjectWithSize(tagCounters, int16(objectCountersContentLength))
tlvObjectCounters.PutInt32(fra.assertions.signCounter)
tlvObjectKeyAuthenticationData := NewFidoUafTlvObjectFromArray(tagUafv1SignedData, []*FidoUafTlvObject{
tlvObjectAaid,
tlvObjectAssertionInfo,
tlvNonceObject,
tlvFinalChallengeHash,
tlvTransactionContentHash,
tlvObjectKeyId,
tlvObjectCounters,
}...)
krdSignature, err := SignDataLocal(tlvObjectKeyAuthenticationData.GetByteArray(), privKeyStr)
if err != nil {
return nil, fmt.Errorf("Error creating signature: %v", err)
}
tlvObjectSignature := NewFidoUafTlvObject(tagSignature, krdSignature)
tlvObjectAuthenticationAssertion := NewFidoUafTlvObjectFromArray(tagUafv1AuthAssertion, tlvObjectKeyAuthenticationData, tlvObjectSignature)
assertionBytes := tlvObjectAuthenticationAssertion.GetByteArray()
encoder := base64.URLEncoding.WithPadding(base64.NoPadding)
base64EncodedAssertion := encoder.EncodeToString(assertionBytes)
return &AuthenticatorSignAssertion{
Assertion: base64EncodedAssertion,
AssertionScheme: uafv1tlv,
}, nil
}