Skip to content

Commit

Permalink
Adding min/max iteration count guards to pbes2-hmac-aeskw algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
dvsekhvalnov committed Nov 23, 2023
1 parent c5d6a57 commit a4584e9
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 6 deletions.
34 changes: 34 additions & 0 deletions jose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1634,6 +1634,40 @@ func (s *TestSuite) TestDecrypt_PBSE2_HS512_A256KW_A256CBC_HS512(c *C) {
c.Assert(test, Equals, `{"exp":1392553211,"sub":"alice","nbf":1392552611,"aud":["https:\/\/app-one.com","https:\/\/app-two.com"],"iss":"https:\/\/openid.net","jti":"586dd129-a29f-49c8-9de7-454af1155e27","iat":1392552611}`)
}

func (s *TestSuite) TestDecrypt_PBSE2_HS512_A256KW_A256CBC_HS512_MinIterationViolation(c *C) {
//given
pbes2Hs512 := DeregisterJwa(PBES2_HS512_A256KW)
RegisterJwa(NewPbse2HmacAesKWAlg(256, 300000, 10000))
token := "eyJhbGciOiJQQkVTMi1IUzUxMitBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwicDJjIjo4MTkyLCJwMnMiOiJCUlkxQ1M3VXNpaTZJNzhkIn0.ovjAL7yRnB_XdJbK8lAaUDRZ-CyVeio8f4pnqOt1FPj1PoQAdEX3S5x6DlzR8aqN_WR5LUwdqDSyUDYhSurnmq8VLfzd3AEe.YAjH6g_zekXJIlPN4Ooo5Q.tutaltxpeVyayXZ9pQovGXTWTf_GWWvtu25Jeg9jgoH0sUX9KCnL00A69e4GJR6EMxalmWsa45AItffbwjUBmwdyklC4ZbTgaovVRs-UwqsZFBO2fpEb7qLajjwra7o4OegzgXDD0jhrKrUusvRWGBvenvumb5euibUxmIfBUcVF1JbdfYxx7ztFeS-QKJpDkE00zyEkViq-QxfrMVl5p7LGmTz8hMrFL3LXLokypZSDgFBfsUzChJf3mlYzxiGaGUqhs7NksQJDoUYf6prPow.XwRVfVTTPogO74RnxZD_9Mse26fTSehna1pbWy4VHfY"

//when
test, headers, err := Decode(token, "top secret")
fmt.Printf("\np2c min iteration err= %v\n", err)

//then
RegisterJwa(pbes2Hs512)
c.Assert(err, NotNil)
c.Assert(test, Equals, "")
c.Assert(headers, IsNil)
}

func (s *TestSuite) TestDecrypt_PBSE2_HS512_A256KW_A256CBC_HS512_MaxIterationViolation(c *C) {
//given
pbes2Hs512 := DeregisterJwa(PBES2_HS512_A256KW)
RegisterJwa(NewPbse2HmacAesKWAlg(256, 8000, 0))
token := "eyJhbGciOiJQQkVTMi1IUzUxMitBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwicDJjIjo4MTkyLCJwMnMiOiJCUlkxQ1M3VXNpaTZJNzhkIn0.ovjAL7yRnB_XdJbK8lAaUDRZ-CyVeio8f4pnqOt1FPj1PoQAdEX3S5x6DlzR8aqN_WR5LUwdqDSyUDYhSurnmq8VLfzd3AEe.YAjH6g_zekXJIlPN4Ooo5Q.tutaltxpeVyayXZ9pQovGXTWTf_GWWvtu25Jeg9jgoH0sUX9KCnL00A69e4GJR6EMxalmWsa45AItffbwjUBmwdyklC4ZbTgaovVRs-UwqsZFBO2fpEb7qLajjwra7o4OegzgXDD0jhrKrUusvRWGBvenvumb5euibUxmIfBUcVF1JbdfYxx7ztFeS-QKJpDkE00zyEkViq-QxfrMVl5p7LGmTz8hMrFL3LXLokypZSDgFBfsUzChJf3mlYzxiGaGUqhs7NksQJDoUYf6prPow.XwRVfVTTPogO74RnxZD_9Mse26fTSehna1pbWy4VHfY"

//when
test, headers, err := Decode(token, "top secret")
fmt.Printf("\np2c max iteration err= %v\n", err)

//then
RegisterJwa(pbes2Hs512)
c.Assert(err, NotNil)
c.Assert(test, Equals, "")
c.Assert(headers, IsNil)
}

func (s *TestSuite) TestEncrypt_PBSE2_HS256_A128KW_A128GCM(c *C) {
//given
payload := `{"hello": "world"}`
Expand Down
51 changes: 45 additions & 6 deletions pbse2_hmac_aeskw.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/sha256"
"crypto/sha512"
"errors"
"fmt"
"hash"

"github.com/dvsekhvalnov/jose2go/arrays"
Expand All @@ -12,15 +13,28 @@ import (
)

func init() {
RegisterJwa(&Pbse2HmacAesKW{keySizeBits: 128, aesKW: &AesKW{keySizeBits: 128}})
RegisterJwa(&Pbse2HmacAesKW{keySizeBits: 192, aesKW: &AesKW{keySizeBits: 192}})
RegisterJwa(&Pbse2HmacAesKW{keySizeBits: 256, aesKW: &AesKW{keySizeBits: 256}})
RegisterJwa(NewPbse2HmacAesKWAlg(128, 310000, 0))
RegisterJwa(NewPbse2HmacAesKWAlg(192, 250000, 0))
RegisterJwa(NewPbse2HmacAesKWAlg(256, 120000, 0))
}

// PBSE2 with HMAC key management algorithm implementation
type Pbse2HmacAesKW struct {
keySizeBits int
aesKW JwaAlgorithm
keySizeBits int
aesKW JwaAlgorithm
maxIterations int64
minIterations int64
}

func NewPbse2HmacAesKWAlg(keySize int, maxIters int64, minIters int64) JwaAlgorithm {
switch keySize {
case 128:
return &Pbse2HmacAesKW{keySizeBits: 128, maxIterations: maxIters, minIterations: minIters, aesKW: &AesKW{keySizeBits: 128}}
case 192:
return &Pbse2HmacAesKW{keySizeBits: 192, maxIterations: maxIters, minIterations: minIters, aesKW: &AesKW{keySizeBits: 192}}
default:
return &Pbse2HmacAesKW{keySizeBits: 256, maxIterations: maxIters, minIterations: minIters, aesKW: &AesKW{keySizeBits: 256}}
}
}

func (alg *Pbse2HmacAesKW) Name() string {
Expand All @@ -46,6 +60,21 @@ func (alg *Pbse2HmacAesKW) WrapNewKey(cekSizeBits int, key interface{}, header m
return nil, nil, err
}

// use user provided iteration counts if any
if p2c, ok := header["p2c"].(int); ok {
iterationCount = p2c
}

if int64(iterationCount) > alg.maxIterations {
return nil, nil, errors.New(
fmt.Sprintf("Pbse2HmacAesKW.Unwrap(): expected 'p2c' to be less than %v but got %v", alg.maxIterations, iterationCount))
}

if int64(iterationCount) < alg.minIterations {
return nil, nil, errors.New(
fmt.Sprintf("Pbse2HmacAesKW.Unwrap(): expected 'p2c' to be higher than %v but got %v", alg.minIterations, iterationCount))
}

header["p2c"] = iterationCount
header["p2s"] = base64url.Encode(saltInput)

Expand All @@ -69,8 +98,18 @@ func (alg *Pbse2HmacAesKW) Unwrap(encryptedCek []byte, key interface{}, cekSizeB
return nil, errors.New("Pbse2HmacAesKW.Unwrap(): expected 'p2c' param in JWT header, but was not found.")
}

if int64(p2c) > alg.maxIterations {
return nil, errors.New(
fmt.Sprintf("Pbse2HmacAesKW.Unwrap(): expected 'p2c' to be less than %v but got %v", alg.maxIterations, p2c))
}

if int64(p2c) < alg.minIterations {
return nil, errors.New(
fmt.Sprintf("Pbse2HmacAesKW.Unwrap(): expected 'p2c' to be higher than %v but got %v", alg.minIterations, p2c))
}

if p2s, ok = header["p2s"].(string); !ok {
return nil, errors.New("Pbse2HmacAesKW.Unwrap(): expected 'p2s' param in JWT header, but was not found.")
return nil, errors.New("Pbse2HmacAesKW.Unwrap(): expected 'p2s' param in JWT header, but was not found")
}

var saltInput []byte
Expand Down

0 comments on commit a4584e9

Please sign in to comment.