Skip to content

Commit

Permalink
Merge pull request #12 from elithrar/doc-changes
Browse files Browse the repository at this point in the history
Changed references to encrypt/decrypt to mask/unmask.
  • Loading branch information
justinas committed Jul 26, 2014
2 parents 0c2731b + 1d8719a commit ec154df
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 39 deletions.
6 changes: 3 additions & 3 deletions context.go
Expand Up @@ -10,7 +10,7 @@ import (
// and not using gorilla's package just because.

type csrfContext struct {
// The encrypted, base64 encoded token
// The masked, base64 encoded token
// That's suitable for use in form fields, etc.
token string
// reason for the failure of CSRF check
Expand Down Expand Up @@ -60,7 +60,7 @@ func Reason(req *http.Request) error {
return ctx.reason
}

// Takes a raw token, encrypts it with a per-request key,
// Takes a raw token, masks it with a per-request key,
// encodes in base64 and makes it available to the wrapped handler
func ctxSetToken(req *http.Request, token []byte) {
cmMutex.Lock()
Expand All @@ -72,7 +72,7 @@ func ctxSetToken(req *http.Request, token []byte) {
contextMap[req] = ctx
}

ctx.token = b64encode(encryptToken(token))
ctx.token = b64encode(maskToken(token))
}

func ctxSetReason(req *http.Request, reason error) {
Expand Down
4 changes: 2 additions & 2 deletions context_test.go
Expand Up @@ -43,7 +43,7 @@ func TestSetsTokenCorrectly(t *testing.T) {

got := contextMap[req].token

if !bytes.Equal(token, decryptToken(b64decode(got))) {
if !bytes.Equal(token, unmaskToken(b64decode(got))) {
t.Errorf("Token set incorrectly: expected %v, got %v", token, got)
}
}
Expand All @@ -60,7 +60,7 @@ func TestGetsTokenCorrectly(t *testing.T) {
ctxSetToken(req, intended)

token = Token(req)
decToken := decryptToken(b64decode(token))
decToken := unmaskToken(b64decode(token))
if !bytes.Equal(intended, decToken) {
t.Errorf("Token has been set to %v, but it's %v", intended, token)
}
Expand Down
12 changes: 6 additions & 6 deletions crypto.go
Expand Up @@ -5,7 +5,7 @@ import (
"io"
)

// Encrypts / decrypts the given data *in place*
// Masks/unmasks the given data *in place*
// with the given key
// Slices must be of the same length, or oneTimePad will panic
func oneTimePad(data, key []byte) {
Expand All @@ -19,27 +19,27 @@ func oneTimePad(data, key []byte) {
}
}

func encryptToken(data []byte) []byte {
func maskToken(data []byte) []byte {
if len(data) != tokenLength {
return nil
}

// tokenLength*2 == len(enckey + token)
result := make([]byte, 2*tokenLength)
// the first half of the result is the encryption key
// the second half is the encrypted token
// the first half of the result is the OTP
// the second half is the masked token itself
key := result[:tokenLength]
token := result[tokenLength:]
copy(token, data)

// generate the encryption key
// generate the random token
io.ReadFull(rand.Reader, key)

oneTimePad(token, key)
return result
}

func decryptToken(data []byte) []byte {
func unmaskToken(data []byte) []byte {
if len(data) != tokenLength*2 {
return nil
}
Expand Down
22 changes: 11 additions & 11 deletions crypto_test.go
Expand Up @@ -17,7 +17,7 @@ func TestOtpPanicsOnLengthMismatch(t *testing.T) {
}()
oneTimePad(data, key)
}
func TestOtpEncryptsCorrectly(t *testing.T) {
func TestOtpMasksCorrectly(t *testing.T) {
data := []byte("Inventors of the shish-kebab")
key := []byte("They stop Cthulhu eating ye.")
// precalculated
Expand All @@ -27,12 +27,12 @@ func TestOtpEncryptsCorrectly(t *testing.T) {
oneTimePad(data, key)

if !bytes.Equal(data, expected) {
t.Errorf("oneTimePad encrypted the data incorrectly: expected %#v, got %#v",
t.Errorf("oneTimePad masked the data incorrectly: expected %#v, got %#v",
expected, data)
}
}

func TestOtpDecryptsCorrectly(t *testing.T) {
func TestOtpUnmasksCorrectly(t *testing.T) {
orig := []byte("a very secret message")
data := make([]byte, len(orig))
copy(data, orig)
Expand All @@ -51,10 +51,10 @@ func TestOtpDecryptsCorrectly(t *testing.T) {
}
}

func TestEncryptsTokenCorrectly(t *testing.T) {
func TestMasksTokenCorrectly(t *testing.T) {
// needs to be of tokenLength
token := []byte("12345678901234567890123456789012")
fullToken := encryptToken(token)
fullToken := maskToken(token)

if len(fullToken) != 2*tokenLength {
t.Errorf("len(fullToken) is not %d, but %d", 2*tokenLength, len(fullToken))
Expand All @@ -63,21 +63,21 @@ func TestEncryptsTokenCorrectly(t *testing.T) {
key := fullToken[:tokenLength]
encToken := fullToken[tokenLength:]

// perform decryption
// perform unmasking
oneTimePad(encToken, key)

if !bytes.Equal(encToken, token) {
t.Errorf("Decrypted token is invalid: expected %v, got %v", token, encToken)
t.Errorf("Unmasked token is invalid: expected %v, got %v", token, encToken)
}
}

func TestDecryptsTokenCorrectly(t *testing.T) {
func TestUnmasksTokenCorrectly(t *testing.T) {
token := []byte("12345678901234567890123456789012")
fullToken := encryptToken(token)
fullToken := maskToken(token)

decToken := decryptToken(fullToken)
decToken := unmaskToken(fullToken)

if !bytes.Equal(decToken, token) {
t.Errorf("Decrypted token is invalid: expected %v, got %v", token, decToken)
t.Errorf("Unmasked token is invalid: expected %v, got %v", token, decToken)
}
}
2 changes: 1 addition & 1 deletion handler.go
Expand Up @@ -180,7 +180,7 @@ func (h *CSRFHandler) RegenerateToken(w http.ResponseWriter, r *http.Request) st
}

func (h *CSRFHandler) setTokenCookie(w http.ResponseWriter, r *http.Request, token []byte) {
// ctxSetToken() does the encryption for us
// ctxSetToken() does the masking for us
ctxSetToken(r, token)

cookie := h.baseCookie
Expand Down
8 changes: 4 additions & 4 deletions handler_test.go
Expand Up @@ -26,7 +26,7 @@ func TestRegenerateToken(t *testing.T) {
writer := httptest.NewRecorder()

req := dummyGet()
token := b64encode(decryptToken(b64decode(hand.RegenerateToken(writer, req))))
token := b64encode(unmaskToken(b64decode(hand.RegenerateToken(writer, req))))

header := writer.Header().Get("Set-Cookie")
expectedPart := fmt.Sprintf("csrf_token=%s;", token)
Expand Down Expand Up @@ -57,7 +57,7 @@ func TestsetTokenCookie(t *testing.T) {
expected_part, header)
}

tokenInContext := decryptToken(b64decode(Token(req)))
tokenInContext := unmaskToken(b64decode(Token(req)))
if !bytes.Equal(tokenInContext, token) {
t.Errorf("RegenerateToken didn't set the token in the context map!"+
" Expected %v, got %v", token, tokenInContext)
Expand Down Expand Up @@ -240,7 +240,7 @@ func TestCorrectTokenPasses(t *testing.T) {
t.Fatal("Cookie was not found in the response.")
}

finalToken := b64encode(encryptToken(b64decode(cookie.Value)))
finalToken := b64encode(maskToken(b64decode(cookie.Value)))

vals := [][]string{
{"name", "Jolene"},
Expand Down Expand Up @@ -288,7 +288,7 @@ func TestPrefersHeaderOverFormValue(t *testing.T) {
t.Fatal("Cookie was not found in the response.")
}

finalToken := b64encode(encryptToken(b64decode(cookie.Value)))
finalToken := b64encode(maskToken(b64decode(cookie.Value)))

vals := [][]string{
{"name", "Jolene"},
Expand Down
22 changes: 11 additions & 11 deletions token.go
Expand Up @@ -15,13 +15,13 @@ const (
/*
There are two types of tokens.
* The unencrypted "real" token consists of 32 random bytes.
* The unmasked "real" token consists of 32 random bytes.
It is stored in a cookie (base64-encoded) and it's the
"reference" value that sent tokens get compared to.
* The encrypted "sent" token consists of 64 bytes:
32 byte key used for one-time pad encryption and
32 byte "real" token encrypted with the said key.
* The masked "sent" token consists of 64 bytes:
32 byte key used for one-time pad masking and
32 byte "real" token masked with the said key.
It is used as a value (base64-encoded as well)
in forms and/or headers.
Expand Down Expand Up @@ -59,24 +59,24 @@ func b64decode(data string) []byte {

// Verifies the sent token equals the real one
// and returns a bool value indicating if tokens are equal.
// Supports encrypted tokens.
// Supports masked tokens.
func verifyToken(realToken, sentToken []byte) bool {
realN := len(realToken)
sentN := len(sentToken)

// sentN == tokenLength means the token is unencrypted
// sentN == 2*tokenLength means the token is encrypted
// sentN == tokenLength means the token is unmasked
// sentN == 2*tokenLength means the token is masked.

if realN == tokenLength && sentN == 2*tokenLength {
return verifyEncrypted(realToken, sentToken)
return verifyMasked(realToken, sentToken)
} else {
return false
}
}

// Verifies the encrypted token
func verifyEncrypted(realToken, sentToken []byte) bool {
sentPlain := decryptToken(sentToken)
// Verifies the masked token
func verifyMasked(realToken, sentToken []byte) bool {
sentPlain := unmaskToken(sentToken)
return subtle.ConstantTimeCompare(realToken, sentPlain) == 1
}

Expand Down
2 changes: 1 addition & 1 deletion token_test.go
Expand Up @@ -54,7 +54,7 @@ func TestVerifyTokenChecksLengthCorrectly(t *testing.T) {
}
}

func TestVerifiesEncryptedTokenCorrectly(t *testing.T) {
func TestVerifiesMaskedTokenCorrectly(t *testing.T) {
realToken := []byte("qwertyuiopasdfghjklzxcvbnm123456")
sentToken := []byte("qwertyuiopasdfghjklzxcvbnm123456" +
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
Expand Down

0 comments on commit ec154df

Please sign in to comment.