-
Notifications
You must be signed in to change notification settings - Fork 1
/
testutils.go
163 lines (138 loc) · 4.22 KB
/
testutils.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
package mfa
import (
"crypto/ecdsa"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"os"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/dynamodb"
u2fsim "github.com/silinternational/serverless-mfa-api-go/u2fsimulator"
)
const localAppID = "http://localhost"
func testAwsConfig() aws.Config {
return aws.Config{
Endpoint: aws.String(os.Getenv("AWS_ENDPOINT")),
Region: aws.String(os.Getenv("AWS_DEFAULT_REGION")),
DisableSSL: aws.Bool(true),
}
}
func testEnvConfig(awsConfig aws.Config) EnvConfig {
envCfg := EnvConfig{
ApiKeyTable: "ApiKey",
WebauthnTable: "WebAuthn",
AwsEndpoint: os.Getenv("AWS_ENDPOINT"),
AwsDefaultRegion: os.Getenv("AWS_DEFAULT_REGION"),
AwsDisableSSL: true,
AWSConfig: &awsConfig,
}
SetConfig(envCfg)
return envCfg
}
func initDb(storage *Storage) error {
var err error
if storage == nil {
awsCfg := testAwsConfig()
storage, err = NewStorage(&aws.Config{
Endpoint: awsCfg.Endpoint,
Region: awsCfg.Region,
DisableSSL: aws.Bool(true),
})
if err != nil {
return err
}
}
// attempt to delete tables in case already exists
tables := map[string]string{"WebAuthn": "uuid", "ApiKey": "value"}
for name, _ := range tables {
deleteTable := &dynamodb.DeleteTableInput{
TableName: aws.String(name),
}
_, err = storage.client.DeleteTable(deleteTable)
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
switch aerr.Code() {
case dynamodb.ErrCodeResourceNotFoundException:
// this is fine
default:
return aerr
}
} else {
return err
}
}
}
// create tables
for table, attr := range tables {
createTable := &dynamodb.CreateTableInput{
AttributeDefinitions: []*dynamodb.AttributeDefinition{
{
AttributeName: aws.String(attr),
AttributeType: aws.String("S"),
},
},
KeySchema: []*dynamodb.KeySchemaElement{
{
AttributeName: aws.String(attr),
KeyType: aws.String("HASH"),
},
},
ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
ReadCapacityUnits: aws.Int64(3),
WriteCapacityUnits: aws.Int64(3),
},
TableName: aws.String(table),
}
_, err = storage.client.CreateTable(createTable)
if err != nil {
return err
}
}
return nil
}
// Encode websafe base64
func encodeBase64(buf []byte) string {
s := base64.URLEncoding.EncodeToString(buf)
return strings.TrimRight(s, "=")
}
// SignResponse as defined by the FIDO U2F Javascript API.
type SignResponse struct {
KeyHandle string `json:"keyHandle"`
SignatureData string `json:"signatureData"`
ClientData string `json:"clientData"`
}
// ClientData as defined by the FIDO U2F Raw Message Formats specification.
type ClientData struct {
Typ string `json:"type"`
Challenge string `json:"challenge"`
Origin string `json:"origin"`
CIDPublicKey json.RawMessage `json:"cid_pubkey"`
}
// GenerateAuthenticationSig appends the clientData to the authData and uses the privateKey's public Key to sign it
// via a sha256 hashing algorithm.
// It returns the base64 encoded version of the marshaled version of the corresponding dsa signature {r:bigInt, s:bigInt}
// It does not use any kind of randomized data in this process
func GenerateAuthenticationSig(authData, clientData []byte, privateKey *ecdsa.PrivateKey) string {
clientDataHash := sha256.Sum256(clientData)
signatureData := append(authData, clientDataHash[:]...)
publicKey := privateKey.PublicKey
h := sha256.New()
h.Write(signatureData)
signHash := h.Sum(nil)
notRandomReader := strings.NewReader(u2fsim.BigStrNotRandom1)
dsaSig, asnSig := u2fsim.GetASN1Signature(notRandomReader, privateKey, signHash)
if !ecdsa.Verify(&publicKey, signHash, dsaSig.R, dsaSig.S) {
panic("start signature is not getting verified for some reason")
}
return encodeBase64(asnSig)
}
// GetPublicKeyAsBytes starts with byte(4) and appends the private key's public key's X and then Y bytes
func GetPublicKeyAsBytes(privateKey *ecdsa.PrivateKey) []byte {
pubKey := privateKey.PublicKey
buf := []byte{0x04} // Has to start with this, apparently
buf = append(buf, pubKey.X.Bytes()...)
buf = append(buf, pubKey.Y.Bytes()...)
return buf
}