Skip to content
This repository has been archived by the owner on Feb 21, 2024. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'mdigger/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Дмитрий Седых committed Jan 8, 2016
2 parents dca209c + 48a0c42 commit ad3a330
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 31 deletions.
6 changes: 0 additions & 6 deletions doc.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
// jwt поддерживает работу с токенами в формате JSON Web Token.
//
// В данной библиотеке я решил ограничиться только поддержкой основного метода подписи — HS256.
// Во-первых, потому что он единственный является обязательным. Во-вторых, совершенно не хотелось
// подключать дополнительные библиотеки без необходимости. В-третьих, с ним получается одна из
// самых коротких подписей, что, как вы понимаете, в прямую касается длины получаемого токена.
// В общем, мне показалось этого достаточно.
package jwt
12 changes: 10 additions & 2 deletions header.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,18 @@ type header struct {
}

// getHeader возвращает сгенерированный заголовок токена с указанием алгоритма для подписи.
func getHeader(alg string) string {
func getHeader(alg string) []byte {
data, _ := json.Marshal(header{
Alg: alg,
Typ: tokenName,
})
return base64.RawURLEncoding.EncodeToString(data)
result := make([]byte, base64.RawURLEncoding.EncodedLen(len(data)))
base64.RawURLEncoding.Encode(result, data)
return result
}

func parseHeader(data []byte) (h *header, err error) {
h = new(header)
err = json.Unmarshal(data, h)
return
}
34 changes: 14 additions & 20 deletions signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,37 @@ import (
"crypto/sha256"
"crypto/sha512"
"encoding/base64"
"encoding/json"
"errors"
"hash"
)

// Signer описывает информацию для подписи токена.
type Signer struct {
hash hash.Hash // алгоритм генерации подписи
name string // название алгоритма
header string // сформированный заголовок токена для данного алгоритма
hash hash.Hash // алгоритм генерации подписи
name string // название алгоритма
}

// NewSignerHS256 возвращает инициализированный подписчик токена, основанный на алгоритме SHA256.
// NewSigner возвращает инициализированный подписчик токена, основанный на алгоритме SHA256.
func NewSignerHS256(key []byte) *Signer {
return &Signer{
hash: hmac.New(sha256.New, key),
name: "HS256",
header: getHeader("HS256"),
hash: hmac.New(sha256.New, key),
name: "HS256",
}
}

// NewSignerHS384 возвращает инициализированный подписчик токена.
// NewSignerHS384 возвращает инициализированный подписчик токена, основанный на алгоритме SHA384.
func NewSignerHS384(key []byte) *Signer {
return &Signer{
hash: hmac.New(sha512.New384, key),
name: "HS384",
header: getHeader("HS384"),
hash: hmac.New(sha512.New384, key),
name: "HS384",
}
}

// NewSignerHS512 возвращает инициализированный подписчик токена.
// NewSignerHS512 возвращает инициализированный подписчик токена, основанный на алгоритме SHA512.
func NewSignerHS512(key []byte) *Signer {
return &Signer{
hash: hmac.New(sha512.New, key),
name: "HS512",
header: getHeader("HS512"),
hash: hmac.New(sha512.New, key),
name: "HS512",
}
}

Expand All @@ -50,7 +45,7 @@ func (s Signer) Sign(token []byte) []byte {
// кодируем в строку и объединяем с заголовком
data := make([]byte, base64.RawURLEncoding.EncodedLen(len(token)))
base64.RawURLEncoding.Encode(data, token)
data = append(append([]byte(s.header), '.'), data...)
data = append(append(getHeader(s.name), '.'), data...)
s.hash.Reset() // сбрасываем состояние
s.hash.Write(data) // добавляем содержимое токена для подсчета
// добавляем к токену подпись и возвращаем сам токен
Expand All @@ -71,9 +66,8 @@ func (s Signer) Parse(token []byte) ([]byte, error) {
if err != nil {
return nil, err
}
data = data[:n]
var header header // разбираем заголовок токена
if err := json.Unmarshal(data, &header); err != nil {
header, err := parseHeader(data[:n]) // разбираем заголовок токена
if err != nil {
return nil, err
}
if header.Typ != "" && header.Typ != tokenName {
Expand Down
20 changes: 17 additions & 3 deletions signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,30 @@ func TestSigner(t *testing.T) {
if err.Error() != "bad token type" {
t.Error("bad token type")
}
_, err = signer.Parse([]byte(getHeader("none") + `.bbb.ccc`))
_, err = signer.Parse(append(getHeader("none"), []byte(`.bbb.ccc`)...))
if err.Error() != "bad token sign algorithm" {
t.Error("bad token sign algorithm")
}
_, err = signer.Parse([]byte(signer.header + `.bbb.ccc`))
_, err = signer.Parse(append(getHeader(signer.name), []byte(`.bbb.ccc`)...))
if err.Error() != "bad token sign" {
t.Error("bad token sign")
}
_, err = signer.Parse([]byte(signer.header + `.bbb.+++`))
_, err = signer.Parse(append(getHeader(signer.name), []byte(`.bbb.+++`)...))
if err == nil {
t.Error("bad token sign data")
}
_, err = signer.Parse([]byte(
`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LisrKw.o3jUAiMkhChgQsKbFbcQySzNjfEoSjp9hIJalHnEVYQ`))
if err != nil {
t.Error("bad token?")
}
}

func TestSigner2(t *testing.T) {
if NewSignerHS384([]byte(`top secret`)) == nil {
t.Error("NewSignerHS384 error")
}
if NewSignerHS512([]byte(`top secret`)) == nil {
t.Error("NewSignerHS512 error")
}
}

0 comments on commit ad3a330

Please sign in to comment.