Challenge 13: ECB cut-and-paste
Probelm
ECB cut-and-pasteWrite a k=v parsing routine, as if for a structured cookie. The routine should take:
foo=bar&baz=qux&zap=zazzle... and produce:
{  foo: 'bar',  baz: 'qux',  zap: 'zazzle'}(you know, the object; I don't care if you convert it to JSON).
Now write a function that encodes a user profile in that format, given an email address. You should have something like:
profile_for("[email protected]")... and it should produce:
{  email: '[email protected]',  uid: 10,  role: 'user'}... encoded as:
[email protected]&uid=10&role=userYour "profile_for" function should not allow encoding metacharacters (& and =). Eat them, quote them, whatever you want to do, but don't let people set their email address to "[email protected]&role=admin".
Now, two more easy functions. Generate a random AES key, then:
Encrypt the encoded user profile under the key; "provide" that to the "attacker".Decrypt the encoded user profile and parse it.Using only the user input to profile_for() (as an oracle to generate "valid" ciphertexts) and the ciphertexts themselves, make a role=admin profile.Code
package challenge13
import (  "crypto/aes"  "encoding/hex"  "fmt"  "log"  "net/url"
  c7 "cryptopals/Set1/challenge7"  c11 "cryptopals/Set2/challenge11"  c9 "cryptopals/Set2/challenge9")
var key []bytevar unknown []byte
func init() {  key = c11.RandBytes(16)}
func Challenge13() {
  ct := profileFor(email)  fmt.Printf("encoded = %#v\n", hex.EncodeToString(ct))
  // email=foobar%40domain.com+++++++ +++&id=100&role= user  ct = profileFor(email)  forge := make([]byte, 0)  forge = append(forge, ct[:3*16]...)  end := make([]byte, 0)  end = append(end, ct[3*16:]...)
  // email=foobar%40d omain.com+++++++ admin&id=100&rol e=user  ct = profileFor(email)  admin := ct[2*16 : 3*16]
  forge = append(forge, admin...)  forge = append(forge, end...)
  vals := decodeProfile(forge)  fmt.Printf("decoded forge = %+v", vals)}
func profileFor(email string) []byte {  pars := make(url.Values)  pars.Add("email", email)  pars.Add("id", "100")  pars.Add("role", "user")  src := []byte(pars.Encode())
  blockSize := len(key)  block, err := aes.NewCipher([]byte(key))  if err != nil {    log.Fatal(err)  }  src = c9.PKCS(src, blockSize)
  dst := make([]byte, len(src))  c7.EncryptAES_ECB(block, dst, src)  return dst}
func decodeProfile(ct []byte) url.Values {  block, err := aes.NewCipher([]byte(key))  if err != nil {    log.Fatal(err)  }
  dst, _ := c7.DecryptAES_ECB(ct, []byte(key), block.BlockSize())  dst, err = c9.UnpadPKCS(dst)  if err != nil {    log.Fatal(err)  }  vals, err := url.ParseQuery(string(dst))  if err != nil {    log.Fatal(err)  }  return vals}