Newer
Older
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
package proj2
// You MUST NOT change what you import. If you add ANY additional
// imports it will break the autograder, and we will be Very Upset.
import (
// You neet to add with
// go get github.com/nweaver/cs161-p2/userlib
"github.com/nweaver/cs161-p2/userlib"
// Life is much easier with json: You are
// going to want to use this so you can easily
// turn complex structures into strings etc...
"encoding/json"
// Likewise useful for debugging etc
"encoding/hex"
// UUIDs are generated right based on the crypto RNG
// so lets make life easier and use those too...
//
// You need to add with "go get github.com/google/uuid"
"github.com/google/uuid"
// Useful for debug messages, or string manipulation for datastore keys
"strings"
// Want to import errors
"errors"
// optional
// strconv
// if you are looking for fmt, we don't give you fmt, but you can use userlib.DebugMsg
// see someUsefulThings() below
)
// This serves two purposes: It shows you some useful primitives and
// it suppresses warnings for items not being imported
func someUsefulThings() {
// Creates a random UUID
f := uuid.New()
userlib.DebugMsg("UUID as string:%v", f.String())
// Example of writing over a byte of f
f[0] = 10
userlib.DebugMsg("UUID as string:%v", f.String())
// takes a sequence of bytes and renders as hex
h := hex.EncodeToString([]byte("fubar"))
userlib.DebugMsg("The hex: %v", h)
// Marshals data into a JSON representation
// Will actually work with go structures as well
d, _ := json.Marshal(f)
userlib.DebugMsg("The json data: %v", string(d))
var g uuid.UUID
json.Unmarshal(d, &g)
userlib.DebugMsg("Unmashaled data %v", g.String())
// This creates an error type
userlib.DebugMsg("Creation of error %v", errors.New(strings.ToTitle("This is an error")))
// And a random RSA key. In this case, ignoring the error
// return value
var pk userlib.PKEEncKey
var sk userlib.PKEDecKey
pk, sk, _ = userlib.PKEKeyGen()
userlib.DebugMsg("Key is %v, %v", pk, sk)
}
// Helper function: Takes the first 16 bytes and
// converts it into the UUID type
func bytesToUUID(data []byte) (ret uuid.UUID) {
for x := range ret {
ret[x] = data[x]
}
return
}
// The structure definition for a file record
type File struct {
Filename string
FileUUID uuid.UUID
FileKey []byte
FileSlice int
}
// The structure definition for a user record
type User struct {
Username string
// You can add other fields here if you want...
// Note for JSON to marshal/unmarshal, the fields need to
// be public (start with a capital letter)
}
// This creates a user. It will only be called once for a user
// (unless the keystore and datastore are cleared during testing purposes)
// It should store a copy of the userdata, suitably encrypted, in the
// datastore and should store the user's public key in the keystore.
// The datastore may corrupt or completely erase the stored
// information, but nobody outside should be able to get at the stored
// User data: the name used in the datastore should not be guessable
// without also knowing the password and username.
// You are not allowed to use any global storage other than the
// keystore and the datastore functions in the userlib library.
// You can assume the user has a STRONG password
func InitUser(username string, password string) (userdataptr *User, err error) {
var userdata User
userdataptr = &userdata
return &userdata, nil
}
// This fetches the user information from the Datastore. It should
// fail with an error if the user/password is invalid, or if the user
// data was corrupted, or if the user can't be found.
func GetUser(username string, password string) (userdataptr *User, err error) {
var userdata User
userdataptr = &userdata
return userdataptr, nil
}
// This stores a file in the datastore.
//
// The name of the file should NOT be revealed to the datastore!
func (userdata *User) StoreFile(filename string, data []byte) {
return
}
// This adds on to an existing file.
//
// Append should be efficient, you shouldn't rewrite or reencrypt the
// existing file, but only whatever additional information and
// metadata you need.
func (userdata *User) AppendFile(filename string, data []byte) (err error) {
return
}
// This loads a file from the Datastore.
//
// It should give an error if the file is corrupted in any way.
func (userdata *User) LoadFile(filename string) (data []byte, err error) {
return
}
// You may want to define what you actually want to pass as a
// sharingRecord to serialized/deserialize in the data store.
type sharingRecord struct {
}
// This creates a sharing record, which is a key pointing to something
// in the datastore to share with the recipient.
// This enables the recipient to access the encrypted file as well
// for reading/appending.
// Note that neither the recipient NOR the datastore should gain any
// information about what the sender calls the file. Only the
// recipient can access the sharing record, and only the recipient
// should be able to know the sender.
func (userdata *User) ShareFile(filename string, recipient string) (
magic_string string, err error) {
return
}
// Note recipient's filename can be different from the sender's filename.
// The recipient should not be able to discover the sender's view on
// what the filename even is! However, the recipient must ensure that
// it is authentically from the sender.
func (userdata *User) ReceiveFile(filename string, sender string,
magic_string string) error {
return nil
}
// Removes access for all others.
func (userdata *User) RevokeFile(filename string) (err error) {
return
}