diff options
-rw-r--r-- | challenge/c13.go | 88 | ||||
-rw-r--r-- | lib/web.go | 94 |
2 files changed, 82 insertions, 100 deletions
diff --git a/challenge/c13.go b/challenge/c13.go index 4c9a6f7..130499d 100644 --- a/challenge/c13.go +++ b/challenge/c13.go @@ -10,18 +10,94 @@ import ( ) func C13() { + type Profile map[string]string + + key, err := lib.RandomBytes(16) + if err != nil { + fmt.Printf("key generation error: %v\n", err) + } + counter := int64(10000) + profiles := make(map[string]Profile, 0) + + genUid := func() int64 { + uid := counter + counter += 1 + + return uid + } + parse := func(encoded string) map[string]string { + m := make(map[string]string, 0) + + kvs := lib.StrSplitAt('&', encoded) + for i := 0; i < len(kvs); i++ { + kv := lib.StrSplitAt('=', kvs[i]) + m[lib.StripSpaceChars(kv[0])] = kv[1] + } + return m + } + encode := func(p Profile) string { + ep := "email=" + p["email"] // Encoded profile. + ep += "&uid=" + p["uid"] + ep += "&role=" + p["role"] + return ep + } + decode := func(encoded string) Profile { + return parse(encoded) + } + encrypt := func(encoded string) []byte { + return lib.AESEncryptECB(lib.StrToBytes(encoded), key) + } + decrypt := func(cipher []byte) string { + return lib.BytesToStr(lib.AESDecryptECB(cipher, key)) + } + sanitize := func(email string) string { + if len(email) < 1 { + return "" + } + se := "" // sanitized email + + // Strip meta characters + for i := 0; i < len(email); i++ { + if email[i] == '&' || email[i] == '=' { + continue + } + se += string(email[i]) + } + return se + } + profileFor := func(email string) string { + e := sanitize(email) + if len(e) == 0 { + panic("email invalid") + } + + if p, ok := profiles[e]; ok { + // Profile already exists. + return encode(p) + } + + // Create profile. + p := make(Profile, 0) + p["email"] = e + p["uid"] = lib.NumToStr(genUid()) + p["role"] = "user" + profiles[e] = p + + return encode(p) + } + adminBlock := lib.BytesToStr(lib.Pkcs7Padding(lib.StrToBytes("admin"), 16)) - ep := lib.WebProfileFor("foo@abacus" + adminBlock) - encryptedEP := lib.WebEncryptProfile(ep) + ep := profileFor("foo@abacus" + adminBlock) + encryptedEP := encrypt(ep) adminBlockCipher := encryptedEP[16:32] // Second block in the cipher - ep = lib.WebProfileFor("foo@abacus") - encryptedEP = lib.WebEncryptProfile(ep) + ep = profileFor("foo@abacus") + encryptedEP = encrypt(ep) for i := 0; i < 16; i++ { // Replace last block with the admin cipher block. encryptedEP[32+i] = adminBlockCipher[i] } - adminEP := lib.WebDecryptProfile(encryptedEP) - adminProfile := lib.WebDecodeProfile(adminEP) + adminEP := decrypt(encryptedEP) + adminProfile := decode(adminEP) fmt.Printf("Admin Encoded Profile: %v\n", adminEP) fmt.Printf("Admin Profile: %v\n", adminProfile) } diff --git a/lib/web.go b/lib/web.go deleted file mode 100644 index 814d016..0000000 --- a/lib/web.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright © 2020 rsiddharth <s@ricketyspace.net> -// SPDX-License-Identifier: ISC - -package lib - -type Profile map[string]string - -var webSessionEncryptionKey []byte -var webUidCounter int64 -var webUserProfiles map[string]Profile = make(map[string]Profile, 0) - -func init() { - var err error - - webSessionEncryptionKey, err = RandomBytes(16) - if err != nil { - panic(err) - } - webUidCounter = 10000 -} - -func WebGenUid() int64 { - uid := webUidCounter - webUidCounter += 1 - - return uid -} - -func WebParseKeyValue(encoded string) map[string]string { - m := make(map[string]string, 0) - - kvs := StrSplitAt('&', encoded) - for i := 0; i < len(kvs); i++ { - kv := StrSplitAt('=', kvs[i]) - m[StripSpaceChars(kv[0])] = kv[1] - } - return m -} - -func WebProfileFor(email string) string { - e := WebSanitizeEmail(email) - if len(e) == 0 { - panic("email invalid") - } - - if p, ok := webUserProfiles[e]; ok { - // Profile already exists. - return WebEncodeProfile(p) - } - - // Create profile. - p := make(Profile, 0) - p["email"] = e - p["uid"] = NumToStr(WebGenUid()) - p["role"] = "user" - webUserProfiles[e] = p - - return WebEncodeProfile(p) -} - -func WebEncodeProfile(p Profile) string { - ep := "email=" + p["email"] // Encoded profile. - ep += "&uid=" + p["uid"] - ep += "&role=" + p["role"] - return ep -} - -func WebDecodeProfile(encoded string) Profile { - return WebParseKeyValue(encoded) -} - -func WebEncryptProfile(encoded string) []byte { - return AESEncryptECB(StrToBytes(encoded), webSessionEncryptionKey) -} - -func WebDecryptProfile(cipher []byte) string { - return BytesToStr(AESDecryptECB(cipher, webSessionEncryptionKey)) -} - -func WebSanitizeEmail(email string) string { - if len(email) < 1 { - return "" - } - se := "" // sanitized email - - // Strip meta characters - for i := 0; i < len(email); i++ { - if email[i] == '&' || email[i] == '=' { - continue - } - se += string(email[i]) - } - return se -} |