From 9b9ecb6e9cad834b383dec8f8657049b673afbc6 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Tue, 12 May 2015 16:54:41 +0200 Subject: [PATCH 01/23] Add pregenerated keys for testing --- spec/fixtures/certs/ec256-private.pem | 8 +++ spec/fixtures/certs/ec256-public.pem | 4 ++ spec/fixtures/certs/ec256-wrong-private.pem | 8 +++ spec/fixtures/certs/ec256-wrong-public.pem | 4 ++ spec/fixtures/certs/ec384-private.pem | 9 ++++ spec/fixtures/certs/ec384-public.pem | 5 ++ spec/fixtures/certs/ec384-wrong-private.pem | 9 ++++ spec/fixtures/certs/ec384-wrong-public.pem | 5 ++ spec/fixtures/certs/ec512-private.pem | 10 ++++ spec/fixtures/certs/ec512-public.pem | 6 +++ spec/fixtures/certs/ec512-wrong-private.pem | 10 ++++ spec/fixtures/certs/ec512-wrong-public.pem | 6 +++ spec/fixtures/certs/rsa-1024-private.pem | 15 ++++++ spec/fixtures/certs/rsa-1024-public.pem | 6 +++ spec/fixtures/certs/rsa-2048-private.pem | 27 ++++++++++ spec/fixtures/certs/rsa-2048-public.pem | 9 ++++ .../fixtures/certs/rsa-2048-wrong-private.pem | 27 ++++++++++ spec/fixtures/certs/rsa-2048-wrong-public.pem | 9 ++++ spec/fixtures/certs/rsa-4096-private.pem | 51 +++++++++++++++++++ spec/fixtures/certs/rsa-4096-public.pem | 14 +++++ 20 files changed, 242 insertions(+) create mode 100644 spec/fixtures/certs/ec256-private.pem create mode 100644 spec/fixtures/certs/ec256-public.pem create mode 100644 spec/fixtures/certs/ec256-wrong-private.pem create mode 100644 spec/fixtures/certs/ec256-wrong-public.pem create mode 100644 spec/fixtures/certs/ec384-private.pem create mode 100644 spec/fixtures/certs/ec384-public.pem create mode 100644 spec/fixtures/certs/ec384-wrong-private.pem create mode 100644 spec/fixtures/certs/ec384-wrong-public.pem create mode 100644 spec/fixtures/certs/ec512-private.pem create mode 100644 spec/fixtures/certs/ec512-public.pem create mode 100644 spec/fixtures/certs/ec512-wrong-private.pem create mode 100644 spec/fixtures/certs/ec512-wrong-public.pem create mode 100644 spec/fixtures/certs/rsa-1024-private.pem create mode 100644 spec/fixtures/certs/rsa-1024-public.pem create mode 100644 spec/fixtures/certs/rsa-2048-private.pem create mode 100644 spec/fixtures/certs/rsa-2048-public.pem create mode 100644 spec/fixtures/certs/rsa-2048-wrong-private.pem create mode 100644 spec/fixtures/certs/rsa-2048-wrong-public.pem create mode 100644 spec/fixtures/certs/rsa-4096-private.pem create mode 100644 spec/fixtures/certs/rsa-4096-public.pem diff --git a/spec/fixtures/certs/ec256-private.pem b/spec/fixtures/certs/ec256-private.pem new file mode 100644 index 00000000..50981287 --- /dev/null +++ b/spec/fixtures/certs/ec256-private.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQACg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHQCAQEEIIwHN0bCzotRDTAB/x+I9deCyxAgbV+Gd7U04ZeSBRISoAcGBSuBBAAK +oUQDQgAEuiysESRZOaHqCxof+ZhyaWkuKyKF84ea1bFq8OnVTkiC0JVSUryrW/UB +JBRZwIYomgq4LRqz2vfrv15kDThCnA== +-----END EC PRIVATE KEY----- diff --git a/spec/fixtures/certs/ec256-public.pem b/spec/fixtures/certs/ec256-public.pem new file mode 100644 index 00000000..3bdf5522 --- /dev/null +++ b/spec/fixtures/certs/ec256-public.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuiysESRZOaHqCxof+ZhyaWkuKyKF84ea +1bFq8OnVTkiC0JVSUryrW/UBJBRZwIYomgq4LRqz2vfrv15kDThCnA== +-----END PUBLIC KEY----- diff --git a/spec/fixtures/certs/ec256-wrong-private.pem b/spec/fixtures/certs/ec256-wrong-private.pem new file mode 100644 index 00000000..260df0b6 --- /dev/null +++ b/spec/fixtures/certs/ec256-wrong-private.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQACg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHQCAQEEICfA4AaomONdmPTzeyrx5U/jugYXTERyb5U3ETTv7Hx7oAcGBSuBBAAK +oUQDQgAEPmuXZT3jpJnEMVPOW6RMsmxeGLOCE1PN6fwvUwOsxv7YnyoQ5/bpo64n ++Jp4slSl1aUNoCBF2oz9bS0iyBo3jg== +-----END EC PRIVATE KEY----- diff --git a/spec/fixtures/certs/ec256-wrong-public.pem b/spec/fixtures/certs/ec256-wrong-public.pem new file mode 100644 index 00000000..511a0def --- /dev/null +++ b/spec/fixtures/certs/ec256-wrong-public.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEPmuXZT3jpJnEMVPOW6RMsmxeGLOCE1PN +6fwvUwOsxv7YnyoQ5/bpo64n+Jp4slSl1aUNoCBF2oz9bS0iyBo3jg== +-----END PUBLIC KEY----- diff --git a/spec/fixtures/certs/ec384-private.pem b/spec/fixtures/certs/ec384-private.pem new file mode 100644 index 00000000..553f27c1 --- /dev/null +++ b/spec/fixtures/certs/ec384-private.pem @@ -0,0 +1,9 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDDxOljqUKw9YNhkluSJIBAYO1YXcNtS+vckd5hpTZ5toxsOlwbmyrnU +Tn+D5Xma1m2gBwYFK4EEACKhZANiAASQwYTiRvXu1hMHceSosMs/8uf50sJI3jvK +kdSkvuRAPxSzhtrUvCQDnVsThFq4aOdZZY1qh2ErJGtzmrx+pEsJvJnvfOTG3NGU +KRalek+LQfVqAUSvDMKlxdkz2e67tso= +-----END EC PRIVATE KEY----- diff --git a/spec/fixtures/certs/ec384-public.pem b/spec/fixtures/certs/ec384-public.pem new file mode 100644 index 00000000..6b7638d4 --- /dev/null +++ b/spec/fixtures/certs/ec384-public.pem @@ -0,0 +1,5 @@ +-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEkMGE4kb17tYTB3HkqLDLP/Ln+dLCSN47 +ypHUpL7kQD8Us4ba1LwkA51bE4RauGjnWWWNaodhKyRrc5q8fqRLCbyZ73zkxtzR +lCkWpXpPi0H1agFErwzCpcXZM9nuu7bK +-----END PUBLIC KEY----- diff --git a/spec/fixtures/certs/ec384-wrong-private.pem b/spec/fixtures/certs/ec384-wrong-private.pem new file mode 100644 index 00000000..1cc5f0d8 --- /dev/null +++ b/spec/fixtures/certs/ec384-wrong-private.pem @@ -0,0 +1,9 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDAfZW47dSKnC5JkSVOk1ERxCIi/IJ1p1WBnVGx4hnrNHy+dxtaZJaF+ +YLInFQ/QbYegBwYFK4EEACKhZANiAAQwXkx4BFBGLXbzl5yVrfxK7er8hSi38iDE +K2+7cdrR137Wn5JUnL4WTwXTzkyUgfBOL3sHNozwfgU03GD/EOUEKqzsIJiz2cbP +bFALd4hS+8T4szDLVC9Jl1W6k0CAtmM= +-----END EC PRIVATE KEY----- diff --git a/spec/fixtures/certs/ec384-wrong-public.pem b/spec/fixtures/certs/ec384-wrong-public.pem new file mode 100644 index 00000000..693bd019 --- /dev/null +++ b/spec/fixtures/certs/ec384-wrong-public.pem @@ -0,0 +1,5 @@ +-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEMF5MeARQRi1285ecla38Su3q/IUot/Ig +xCtvu3Ha0dd+1p+SVJy+Fk8F085MlIHwTi97BzaM8H4FNNxg/xDlBCqs7CCYs9nG +z2xQC3eIUvvE+LMwy1QvSZdVupNAgLZj +-----END PUBLIC KEY----- diff --git a/spec/fixtures/certs/ec512-private.pem b/spec/fixtures/certs/ec512-private.pem new file mode 100644 index 00000000..fddd8889 --- /dev/null +++ b/spec/fixtures/certs/ec512-private.pem @@ -0,0 +1,10 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIB0/+ffxEj7j62xvGaB5pvzk888e412ESO/EK/K0QlS9dSF8+Rj1rG +zqpRB8fvDnoe8xdmkW/W5GKzojMyv7YQYumgBwYFK4EEACOhgYkDgYYABAEw74Yw +aTbPY6TtWmxx6LJDzCX2nKWCPnKdZcEH9Ncu8g5RjRBRq2yacja3OoS6nA2YeDng +reBJxZr376P6Ns6XcQFWDA6K/MCTrEBCsPxXZNxd8KR9vMGWhgNtWRrcKzwJfQkr +suyehZkbbYyFnAWyARKHZuV7VUXmeEmRS/f93MPqVA== +-----END EC PRIVATE KEY----- diff --git a/spec/fixtures/certs/ec512-public.pem b/spec/fixtures/certs/ec512-public.pem new file mode 100644 index 00000000..a74a57b0 --- /dev/null +++ b/spec/fixtures/certs/ec512-public.pem @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBMO+GMGk2z2Ok7VpsceiyQ8wl9pyl +gj5ynWXBB/TXLvIOUY0QUatsmnI2tzqEupwNmHg54K3gScWa9++j+jbOl3EBVgwO +ivzAk6xAQrD8V2TcXfCkfbzBloYDbVka3Cs8CX0JK7LsnoWZG22MhZwFsgESh2bl +e1VF5nhJkUv3/dzD6lQ= +-----END PUBLIC KEY----- diff --git a/spec/fixtures/certs/ec512-wrong-private.pem b/spec/fixtures/certs/ec512-wrong-private.pem new file mode 100644 index 00000000..b6ec7b73 --- /dev/null +++ b/spec/fixtures/certs/ec512-wrong-private.pem @@ -0,0 +1,10 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIHbAgEBBEG/KbA2oCbiCT6L3V8XSz2WKBy0XhGvIFbl/ZkXIXnkYt+1B7wViSVo +KCHuMFsi6xU/5nE1EuDG2UsQJmKeAMkIOKAHBgUrgQQAI6GBiQOBhgAEAG0TFWe5 +cZ5DZIyfuysrCoQySTNxd+aT8sPIxsx7mW6YBTsuO6rEgxyegd2Auy4xtikxpzKv +soMXR02999Aaus2jAAt/wxrhhr41BDP4MV0b6Zngb72hna0pcGqit5OyU8AbOJUZ ++rdyowRGsOY+aPbOyVhdNcsEdxYC8GdIyCQLBC1H +-----END EC PRIVATE KEY----- diff --git a/spec/fixtures/certs/ec512-wrong-public.pem b/spec/fixtures/certs/ec512-wrong-public.pem new file mode 100644 index 00000000..a84be38c --- /dev/null +++ b/spec/fixtures/certs/ec512-wrong-public.pem @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAbRMVZ7lxnkNkjJ+7KysKhDJJM3F3 +5pPyw8jGzHuZbpgFOy47qsSDHJ6B3YC7LjG2KTGnMq+ygxdHTb330Bq6zaMAC3/D +GuGGvjUEM/gxXRvpmeBvvaGdrSlwaqK3k7JTwBs4lRn6t3KjBEaw5j5o9s7JWF01 +ywR3FgLwZ0jIJAsELUc= +-----END PUBLIC KEY----- diff --git a/spec/fixtures/certs/rsa-1024-private.pem b/spec/fixtures/certs/rsa-1024-private.pem new file mode 100644 index 00000000..7f01c002 --- /dev/null +++ b/spec/fixtures/certs/rsa-1024-private.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDO/ahgFDvniFoQ1dm+MdnkBi+Ts5W9AtQNgw4ZHIdPnqEzSgW7 +0opKEu8hnlLqsIyU2BC2op/xOanipdbXObuFlA6bth1cYRI+YJlR3BbPGOIL6YbJ +ud9m0gIsBlCDLm4e/E45ZS+emudISP7/SF7zxvxZlnr1z7HTm7nIIVBvuQIDAQAB +AoGBAMzFQAccvU6GI6O4C5sOsiHUxMh3xtCftaxQVGgfQvVPVuXoeteep1Q0ewFl +IV4vnkO5pH8pTtVTWG9x5KIy6QCql4qvr2jkOm4mo9uogrpNklvBl2lN4Lxubj0N +mGRXaM3hckZl8+JT6uzfBfjy+pd8AOigJGPQCOZn4gmANW7pAkEA82Nh4wpj6ZRU +NBiBq3ONZuH4xJm59MI2FWRJsGUFUYdSaFwyKKim52/13d8iUb7v9utWQFRatCXz +Lqw9fQyVrwJBANm3dBOVxpUPrYEQsG0q2rdP+u6U3woylxwtQgJxImZKZmmJlPr8 +9v23rhydvCe1ERPYe7EjF4RGWVPN3KLdExcCQDdzNfL3BApMS97OkoRQQC/nXbjU +2SPlN1MqVQuGCG8pqGG0V40h11y1CkvxMS10ldEojq77SOrwFnZUsXGS82sCQQC6 +XdO7QCaxSq5XIRYlHN4EtS40NLOIYy3/LK6osHel4GIyTVd+UjSLk0QzssJxqwln +V5TqWQO0cxPcLQiFUYEZAkEA2G84ilb9QXOgbNyoE1VifNk49hhodbSskLb86uwY +Vgtzq1ZsqoPBCasr4WRiXt270n+mo5dNYRlZwiUn9lH78Q== +-----END RSA PRIVATE KEY----- diff --git a/spec/fixtures/certs/rsa-1024-public.pem b/spec/fixtures/certs/rsa-1024-public.pem new file mode 100644 index 00000000..7bec6ef0 --- /dev/null +++ b/spec/fixtures/certs/rsa-1024-public.pem @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO/ahgFDvniFoQ1dm+MdnkBi+T +s5W9AtQNgw4ZHIdPnqEzSgW70opKEu8hnlLqsIyU2BC2op/xOanipdbXObuFlA6b +th1cYRI+YJlR3BbPGOIL6YbJud9m0gIsBlCDLm4e/E45ZS+emudISP7/SF7zxvxZ +lnr1z7HTm7nIIVBvuQIDAQAB +-----END PUBLIC KEY----- diff --git a/spec/fixtures/certs/rsa-2048-private.pem b/spec/fixtures/certs/rsa-2048-private.pem new file mode 100644 index 00000000..dab50df2 --- /dev/null +++ b/spec/fixtures/certs/rsa-2048-private.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA4GzZTLU48c4WbyvHi+QKrB71x+T0eq5hqDbQqnlYjhD1Ika7 +io1iplsdJWJuyxfYbUkb2Ol0fj4koZ/GS6lgCZr4+8UHbr1qf0Eu5HZSpszs2YxY +8U5RHnrpw67co7hlgAR9HbyNf5XIYgLV9ldHH/eazwnc3F/hgNsV0xjScVilejgo +cJ4zcsyymvW8t42lteM7bI867ZuJhGop/V+Y0HFyrMsPoQyLuCUpr6ulOfrkr7ZO +dhAIG8r1HcjOp/AUjM15vfXcbUZjkM/VloifX1YitU3upMGJ8/DpFGffMOImrn5r +6BT494V8rRyN2qvQoAkLJpqZ0avLxwiR2lgVQQIDAQABAoIBAEH0Ozgr2fxWEInD +V/VooypKPvjr9F1JejGxSkmPN9MocKIOH3dsbZ1uEXa3ItBUxan4XlK06SNgp+tH +xULfF/Y6sQlsse59hBq50Uoa69dRShn1AP6JgZVvkduMPBNxUYL5zrs6emsQXb9Q +DglDRQfEAJ7vyxSIqQDxYcyT8uSUF70dqFe+E9B2VE3D6ccHc98k41pJrAFAUFH1 +wwvDhfyYr7/Ultut9wzpZvU1meF3Vna3GOUHfxrG6wu1G+WIWHGjouzThsc1qiVI +BtMCJxuCt5fOXRbU4STbMqhB6sZHiOh6J/dZU6JwRYt+IS8FB6kCNFSEWZWQledJ +XqtYSQECgYEA9nmnFTRj3fTBq9zMXfCRujkSy6X2bOb39ftNXzHFuc+I6xmv/3Bs +P9tDdjueP/SnCb7i/9hXkpEIcxjrjiqgcvD2ym1hE4q+odMzRAXYMdnmzI34SVZE +U5hYJcYsXNKrTTleba7QgqdORmyJ9FwqLO40udvmrZMY223XDwgRkOkCgYEA6RkO +5wjjrWWp/G1YN3KXZTS1m2/eGrUThohXKAfAjbWWiouNLW2msXrxEWsPRL6xKiHu +X9cwZwzi3MstAgk+bphUGUVUkGKNDjWHJA25tDYjbPtkd6xbL4eCHsKpNL3HNYr9 +N0CIvgn7qjaHRBem0iK7T6keY4axaSVddEwYapkCgYEA13K5qaB1F4Smcpt8DTWH +vPe8xUUaZlFzOJLmLCsuwmB2N8Ppg2j7RspcaxJsH021YaB5ftjWm+ipMSr8ZPY/ +8JlPsNzxuYpTXtNmAbT2KYVm6THEch61dTk6/DIBf1YrpUJbl5by7vJeStL/uBmE +SGgksL5XIyzs0opuLdaIvFkCgYAyBLWE8AxjFfCvAQuwAj/ocLITo6KmWnrRIIqL +RXaVMgUWv7FQsTnW1cnK8g05tC2yG8vZ9wQk6Mf5lwOWb0NdWgSZ0528ydj41pWk +L+nMeN2LMjqxz2NVxJ8wWJcUgTCxFZ0WcRumo9/D+6V1ABpE9zz4cBLcSnfhVypB +nV6T6QKBgQCSZNCQ9HPxjAgYcsqc5sjNwuN1GHQZSav3Tye3k6zHENe1lsteT9K8 +xciGIuhybKZBvB4yImIIHCtnH+AS+mHAGqHarjNDMfvjOq0dMibPx4+bkIiHdBIH +Xz+j5kmntvFiUnzr0Z/Tcqo+r8FvyCo1YWgwqGP8XoFrswD7gy7cZw== +-----END RSA PRIVATE KEY----- diff --git a/spec/fixtures/certs/rsa-2048-public.pem b/spec/fixtures/certs/rsa-2048-public.pem new file mode 100644 index 00000000..c80a9523 --- /dev/null +++ b/spec/fixtures/certs/rsa-2048-public.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4GzZTLU48c4WbyvHi+QK +rB71x+T0eq5hqDbQqnlYjhD1Ika7io1iplsdJWJuyxfYbUkb2Ol0fj4koZ/GS6lg +CZr4+8UHbr1qf0Eu5HZSpszs2YxY8U5RHnrpw67co7hlgAR9HbyNf5XIYgLV9ldH +H/eazwnc3F/hgNsV0xjScVilejgocJ4zcsyymvW8t42lteM7bI867ZuJhGop/V+Y +0HFyrMsPoQyLuCUpr6ulOfrkr7ZOdhAIG8r1HcjOp/AUjM15vfXcbUZjkM/Vloif +X1YitU3upMGJ8/DpFGffMOImrn5r6BT494V8rRyN2qvQoAkLJpqZ0avLxwiR2lgV +QQIDAQAB +-----END PUBLIC KEY----- diff --git a/spec/fixtures/certs/rsa-2048-wrong-private.pem b/spec/fixtures/certs/rsa-2048-wrong-private.pem new file mode 100644 index 00000000..7cae44c6 --- /dev/null +++ b/spec/fixtures/certs/rsa-2048-wrong-private.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAzHAVGaW9j4l3/b4ngcjjoIoIcnsQEWOMqErb5VhLZMGIq1gE +O5qxPDAwooKsNotzcAOB3ZyLn7p5D+dmOrNUYkYWgYITNGeSifrnVqQugd5Fh1L8 +K7zOGltUo2UtjbN4uJ56tzxBMZp2wejs2/Qu0eu0xZK3To+YkDcWOk92rmNgmUSQ +C/kNyIOj+yBvOo3wTk6HvbhoIarCgJ6Lay1v/hMLyQLzwRY/Qfty1FTIDyTv2dch +47FsfkZ1KAL+MbUnHuCBPzGxRjXa8Iy9Z7YGxrYasUt1b0um64bscxoIiCu8yLL8 +jlg01Rwrjr/MTwKRhwXlMp8B7HTonwtaG6arJwIDAQABAoIBAGFR4dmJusl/qW1T +fj8cQLAFxaupxaZhe24J5NAyzgEy2Dqo9ariIwkB78UM66ozjEqAgOvcP+NTw5m8 +kD/VapA1yTTxlO7XdzzUAhiOo80S4IphCMZRZNPLMmluGtdf3lIUr1pXBrn0TCBX +H5o9jaREzpNXGof9d6T/dEdh2J9+uE/p1xE5GSxQfaPheZzCG7636La/DcArg/UR ++TusPqp62BEmk96pE/KKJRmEeH+WnPfSh6sMpLxi3hkEU7AynpliGT6Z6xV4csBI +S/rdpkcj5DWpbnQzkwdrnL2Q+POEq/vlx5/NlezvtQPNLvQWDyY4yBCoMKGb3EbX +xrxP7MECgYEA/kwe4P0Mqk+087IyhjDBGPfcMt8gfYc9nzNfIYSWdSwuSag/hqHq +I4GwHQzUV9ix3iM6w5hin10yAzWxCYZg9hquV+lSvNNpGB76FX6oOqwuAhyQMRwv +eW+VUyfFXeJugwL5JuIaNTvwPpQVDHYtELLifie+uzJ5HC6dhg/XchcCgYEAzc5/ ++IXjOlExd/mBgFk/5Y87ifA0ZOgbaJXifYgU0aNSgz1piHxU3n2p4jJ9lSdwwCl2 +Fb5EN7666t20PL5QcXJ5ZdaTRLzRlYiqTWzfYHBgttbB1Jl3Ed9GsKuzRgaRqGFC +ANJSqZlKG0NZ3keRtuKdFwq+IVOnsQr9g0TZiXECgYEAqUgtCiMKCloTIGMQpSnR +cXiWWjsUmturls4Q1vQ3YHrvuVLKLyqb/dT4Uu5WcMAs765OESThCit0/pQAbVHK +PCpYwubskAzAGjGM00BEZwJ1gixXhIm5xMIWCowgI7Z3ULlq+IptXeCvtkjHlksZ +BtO+WLLGkkEwRCV38WWcSzMCgYA/Xxqgl/mD94RYAQgTUWgPc69Nph08BQyLg7ue +E8z1UGkT6FEaqc4oRGGPOSTaTK63PQ0TXOb8k0pTD7l0CtYSWMFwzkXCoLGYbeCi +vqd5tqDRLAe7QxYa9rl5pSUqptMrGeeNATZa6sya4H5Hp5oCyny8n54z/OJh7ZRq +W0TwwQKBgQDDP7ksm2pcqadaVAmODdOlaDHbaEcxp8wN7YVz0lM3UpJth96ukbj7 +S39eJhXYWOn6oJQb/lN9fGOYqjg3y6IchGZDp67ATvWYvn/NY0R7mt4K4oHx5TuN +rSQlP3WmOGv8Kemw892uRfW/jZyBEHhsfS213WDttVPn9F635GdNWw== +-----END RSA PRIVATE KEY----- diff --git a/spec/fixtures/certs/rsa-2048-wrong-public.pem b/spec/fixtures/certs/rsa-2048-wrong-public.pem new file mode 100644 index 00000000..8d496014 --- /dev/null +++ b/spec/fixtures/certs/rsa-2048-wrong-public.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzHAVGaW9j4l3/b4ngcjj +oIoIcnsQEWOMqErb5VhLZMGIq1gEO5qxPDAwooKsNotzcAOB3ZyLn7p5D+dmOrNU +YkYWgYITNGeSifrnVqQugd5Fh1L8K7zOGltUo2UtjbN4uJ56tzxBMZp2wejs2/Qu +0eu0xZK3To+YkDcWOk92rmNgmUSQC/kNyIOj+yBvOo3wTk6HvbhoIarCgJ6Lay1v +/hMLyQLzwRY/Qfty1FTIDyTv2dch47FsfkZ1KAL+MbUnHuCBPzGxRjXa8Iy9Z7YG +xrYasUt1b0um64bscxoIiCu8yLL8jlg01Rwrjr/MTwKRhwXlMp8B7HTonwtaG6ar +JwIDAQAB +-----END PUBLIC KEY----- diff --git a/spec/fixtures/certs/rsa-4096-private.pem b/spec/fixtures/certs/rsa-4096-private.pem new file mode 100644 index 00000000..ddee0731 --- /dev/null +++ b/spec/fixtures/certs/rsa-4096-private.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJJwIBAAKCAgEAqETmgWBi5rCmb7euJplA/9xs65+bncc9Yvs5zjyycXSW82Jf +RuyguGm0OvA2wog24dR4N2kT/87DcGtp5JqJWADVFNr+2V2r6i57/OMLruRpn3p2 +r95dmo0COE+BxPFl7XEBT8JbH57ZtpgcB3/xkS14nLOWFf96hrXPlXJC+VMVKVZm +A8k2LRh42vT5wUf4U0Doy/p7yFNSFFa6Q8wwe4TBy/z/f+rhFD1w8rxlYjallee/ +ocm7bjZCwbJGMm7orLViqWfsFX3O35PeoJ5h/7uJ7iRwvTFERkTdwWP/0BeKBeIt +BR3YFc2mut+V9W+WKRkMSL6Crc+oVSx3p8aB7j9SZFzQiRtes4BYETpX1xl2mgIq +5hvsFbLw7ESrlIodiwUMTrSIid2DQ6q80kv1zXPr4+Id6L0sJLxPCaXnTmNtasSw +yedJJYxLjwhHJwtzFAeaq18H3O791YKhjAJ6YxK3zJ59jTE6Pkvqjq183f2PGHVR +vgSN7aCmI6MBUUB5wDP2K8zX2sh40/uPDVSd6ei1vl3DpPk+h8iExx6AzbohfqZ+ +5RUUNx127L3MaQvOVC5TxV+R99gwKW++wzcVuO3m2KqVUj+K1uYBy3KBCUMBbckp +EWGbN++jcdV5oJX6fsC66nOmKlntYwCL/pRww+oLsbzF8J3dxeDbKNF9JDsCAwEA +AQKCAgBJF8TZJjlP5CQoGy227pNhkSpvH6HFY6qyuFZf09XfmrmHd4/Tiy41bRUx +FO90iR7t8hFWYHqjf/k9eCtDdi164MGukYJqgVoQG6kYLLgCfI21DMlJk9otLFtu +gnroRcP05EWhk9dpYONJgcGLMHSKj6n4x7nGTHe41HkbfcrB6ukiT7l4o4q5BAxb +cFadMtoXr/ZvxJrIZgkddJ7snGHjBcP5DCkgM7MZy6aoilWv1/UNrOF9MdgNA9zz +rrD3b136x7/XvqC6pS+bxuvJ8YK4R4qeu42NYT07GOcK/pk8lz0JWTodIt2eevqV +6lGFj7c2mv7PCpJRVgbVGL/RTVVap/+jbcRVLdnYKsII/dANG7iXnfwRgkLWet5D +OOsPuvIuyiSaJIwcdRE3SSO+tZhKLt+gh/oLxBPw5Ex0FwsVTtYn3Q/X3EAx+Wph +eFcRr3TVkDg0MfdWWkgk16DvYB5cWc29coTaH1g+2juadNHbtVAigwJorKc6sxH3 +QGsW0WQJ8ZRZgJkSUuu3nr7QD3ZrgHptONQAh1RWGnIWi6OlMfaPdMo+SDnnL5SG +mpOPjWadDc1XvMFnKQYMYB5GWU/ZNmnZmDLyg1Pc0Y+qRUc0s83nZFHN60KnUrSz +0MZDspSFtr0fMx0b2/EB4EbuXd3QjQURF6P6HtWBu6oFnzu1AQKCAQEA2R9BKJgJ +vNP+DUu8NBzwmi0cKlAiaxt+w90i5DWq1XWPKgi+RVLkaQSJqHoYQVNgEwL/cWxp +s2r3GCMNIdOrGdcm8dX/6UYFpRaFcViTycVEA7cwZOMppgqr2Q+ZYX42K7HObUVL +JGvdEWWWfSsynUGsrG87DC1gl94ANxCdqkZdbW5d3X0w5v7M/1tlrmAeskZSZpeT +8BwwM6REb0U/B4/i8TLtLi/PGmMTOIxW41uKS/S6kq/gwyv+jNNO0ljhPt25iSbV +K5ZHS4YuPKLl0tZMaOkPco9s6t4ES/Y317zQoTzUkAAkkFO4QPzRZL0ESqVBNR0h +Ao7FLmFZzFHpoQKCAQEAxmZBn0UrJLXkD7bw66y4RwzjQYmxLlkEl3uvjrvVSuL1 +mAHDW58aGIpFFZ8QSTtNewIBQYNifp/cdFHAagqtl/iMGEegaOpJAKu/ykrkfZUp +7mYDNng4ZWpypeKaGMAQoNzZiUpF+BDnqbeb/kgYu6sNlh9gRHR79rgAuZQxZ/1B +tE8WcUFi4CnTq2QLqX4LwMuZHWXAJQoMoW3K5av+J544lIM6GdMJuIONtBBkKVQD +ErrJ0bqYeykrFS6pKl/NBCZLGo5xFFRiYEdZ1GlA3uW3EGKppz6PS7194+x5UVts +xZPUfkgdFjWCczkl4JDoWfaNn5sgXtiVbGh1n3gYWwKCAQB7vHEg1kyuXU4qe5/d +PyTraIvlnVeQHNJIgy0QS3l5Pw8A0IzG6y+anehpqHNMP1zAWPQEytkOVAZPriIc +xgl7p37dUa0PX0V2SPhxmR5YXeCeEXc197PTmb9H67jos8nhauqOoW/qaMJK2M9D +tCubLUNf3eAT14R16CHNP93qnUE/TSeXQ3JsIofne0neb47u4F6zcuzvaNEbjSEn +HJqID7sw5GoA6WQo0I+yqWAXICMXmHf/gtYfxGHEFeSUwexULH5BKG1R8sncw7J0 +Ag3h8xkGrNON4SkcTLy8Iay/eS6YxRcKndo4mk2mU65tr77TX4xi3Z/jWkQLY5WO +eJwhAoIBABO17wkSxyGDjJ/fDfpsE3bDmgRV2KuBHoqqOBvXH26sM7ghXLZKjT4o +5ooqXmTYJm91GIjYs71exnkr8hDW9L4nbEuxOgeSVyRg69H+NMshOaQ8sE8GDJxO +wgsnAyY4Vq6UomwYW/E0RL/AxRezM/nZGaVzgo3qgLJXP4MwbOQm7hMq1FD2LQuW +PDhH3Ty+kA5ca97W0Asd/3k+Pi0pNDvdZUOj8e7E369cKoTcKAdPGGsQ8aILhsCd +q3EUTKwwDl8+KrH9utBJPejQzeTjfBVo/xH6q145QeVFcy9ku/zQN3M9p5vQMEuX +j1lBMTkpTFw7uYBE2idyHw5BJoZsWQcCggEADfZTChqnOncItSflzGoaAACrr4/x +KyT/4A+cPMCs11JN9J+EWsCezya2o1l/NF7YPcBR4qjCmFMEiq5GxH5fGLQp0aa7 +V13mHA8XBQ25OW2K7BGJhMHdbuvTnl6jsOfC4+t7P2bUAYxoP6/ncxTzZ5OlBN5k +aMv9firWl1kSKK75ww9DWn6j0rQ4dBetwX45EMcs+iKIdydg0fmJxR2EJ+uQsCFy +xcWBEDqV7qLUi6UrAPL3v/DXUv9wKcKOTbKw/aNE8+YTWMUO330GCJ5cVU1eTL5t +UrcNKOJkFIj7jJUCzv6vcy++hMJEbNXnnTVRnky6e9C2vwzMl33njntapg== +-----END RSA PRIVATE KEY----- diff --git a/spec/fixtures/certs/rsa-4096-public.pem b/spec/fixtures/certs/rsa-4096-public.pem new file mode 100644 index 00000000..01055eb0 --- /dev/null +++ b/spec/fixtures/certs/rsa-4096-public.pem @@ -0,0 +1,14 @@ +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqETmgWBi5rCmb7euJplA +/9xs65+bncc9Yvs5zjyycXSW82JfRuyguGm0OvA2wog24dR4N2kT/87DcGtp5JqJ +WADVFNr+2V2r6i57/OMLruRpn3p2r95dmo0COE+BxPFl7XEBT8JbH57ZtpgcB3/x +kS14nLOWFf96hrXPlXJC+VMVKVZmA8k2LRh42vT5wUf4U0Doy/p7yFNSFFa6Q8ww +e4TBy/z/f+rhFD1w8rxlYjallee/ocm7bjZCwbJGMm7orLViqWfsFX3O35PeoJ5h +/7uJ7iRwvTFERkTdwWP/0BeKBeItBR3YFc2mut+V9W+WKRkMSL6Crc+oVSx3p8aB +7j9SZFzQiRtes4BYETpX1xl2mgIq5hvsFbLw7ESrlIodiwUMTrSIid2DQ6q80kv1 +zXPr4+Id6L0sJLxPCaXnTmNtasSwyedJJYxLjwhHJwtzFAeaq18H3O791YKhjAJ6 +YxK3zJ59jTE6Pkvqjq183f2PGHVRvgSN7aCmI6MBUUB5wDP2K8zX2sh40/uPDVSd +6ei1vl3DpPk+h8iExx6AzbohfqZ+5RUUNx127L3MaQvOVC5TxV+R99gwKW++wzcV +uO3m2KqVUj+K1uYBy3KBCUMBbckpEWGbN++jcdV5oJX6fsC66nOmKlntYwCL/pRw +w+oLsbzF8J3dxeDbKNF9JDsCAwEAAQ== +-----END PUBLIC KEY----- From 1de4b87d28e8ded114994d0d7ea921a21e1df385 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Tue, 12 May 2015 16:56:23 +0200 Subject: [PATCH 02/23] Rename spec/helper spec/spec_helper Add fixtures/certs path Update configuration --- spec/{helper.rb => spec_helper.rb} | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) rename spec/{helper.rb => spec_helper.rb} (65%) diff --git a/spec/helper.rb b/spec/spec_helper.rb similarity index 65% rename from spec/helper.rb rename to spec/spec_helper.rb index 747cfae2..4deef7d9 100644 --- a/spec/helper.rb +++ b/spec/spec_helper.rb @@ -18,4 +18,15 @@ SimpleCov.start if ENV['COVERAGE'] CodeClimate::TestReporter.start if ENV['CODECLIMATE_REPO_TOKEN'] -require "#{File.dirname(__FILE__)}/../lib/jwt.rb" +CERT_PATH = File.join(File.dirname(__FILE__), 'fixtures', 'certs') + +RSpec.configure do |config| + config.expect_with :rspec do |c| + c.syntax = [:should, :expect] + end + + config.run_all_when_everything_filtered = true + config.filter_run :focus + + config.order = 'random' +end From a34e2386493312524d71f7a5dff1641fa69ae79a Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Tue, 12 May 2015 19:48:24 +0200 Subject: [PATCH 03/23] Update certificates Used wrong curve -.- :/ --- spec/fixtures/certs/ec256-private.pem | 8 ++++---- spec/fixtures/certs/ec256-public.pem | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/fixtures/certs/ec256-private.pem b/spec/fixtures/certs/ec256-private.pem index 50981287..40c7a8f6 100644 --- a/spec/fixtures/certs/ec256-private.pem +++ b/spec/fixtures/certs/ec256-private.pem @@ -1,8 +1,8 @@ -----BEGIN EC PARAMETERS----- -BgUrgQQACg== +BggqhkjOPQMBBw== -----END EC PARAMETERS----- -----BEGIN EC PRIVATE KEY----- -MHQCAQEEIIwHN0bCzotRDTAB/x+I9deCyxAgbV+Gd7U04ZeSBRISoAcGBSuBBAAK -oUQDQgAEuiysESRZOaHqCxof+ZhyaWkuKyKF84ea1bFq8OnVTkiC0JVSUryrW/UB -JBRZwIYomgq4LRqz2vfrv15kDThCnA== +MHcCAQEEIJmVse5uPfj6B4TcXrUAvf9/8pJh+KrKKYLNcmOnp/vPoAoGCCqGSM49 +AwEHoUQDQgAEAr+WbDE5VtIDGhtYMxvEc6cMsDBc/DX1wuhIMu8dQzOLSt0tpqK9 +MVfXbVfrKdayVFgoWzs8MilcYq0QIhKx/w== -----END EC PRIVATE KEY----- diff --git a/spec/fixtures/certs/ec256-public.pem b/spec/fixtures/certs/ec256-public.pem index 3bdf5522..e6f22827 100644 --- a/spec/fixtures/certs/ec256-public.pem +++ b/spec/fixtures/certs/ec256-public.pem @@ -1,4 +1,4 @@ -----BEGIN PUBLIC KEY----- -MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuiysESRZOaHqCxof+ZhyaWkuKyKF84ea -1bFq8OnVTkiC0JVSUryrW/UBJBRZwIYomgq4LRqz2vfrv15kDThCnA== +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAr+WbDE5VtIDGhtYMxvEc6cMsDBc +/DX1wuhIMu8dQzOLSt0tpqK9MVfXbVfrKdayVFgoWzs8MilcYq0QIhKx/w== -----END PUBLIC KEY----- From fa352724c8e0b8dde490541d8de04b569664068e Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Tue, 12 May 2015 19:49:16 +0200 Subject: [PATCH 04/23] Add refactored specs Test coverage at 91% Few validation specs missing --- lib/jwt.rb | 2 +- spec/jwt_spec.rb | 602 ++++++++++++----------------------------------- 2 files changed, 154 insertions(+), 450 deletions(-) diff --git a/lib/jwt.rb b/lib/jwt.rb index 1b674742..ab5474b3 100644 --- a/lib/jwt.rb +++ b/lib/jwt.rb @@ -203,7 +203,7 @@ def verify_signature(algo, key, signing_input, signature) fail JWT::VerificationError, 'Algorithm not supported' end rescue OpenSSL::PKey::PKeyError - fail JWT::VerificationError, 'Signature verification raised' + raise JWT::VerificationError, 'Signature verification raised' ensure OpenSSL.errors.clear end diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index ecf7a705..41b040ad 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -1,500 +1,204 @@ -# encoding: utf-8 -require 'helper' +require 'spec_helper' +require 'jwt' describe JWT do - before do - @payload = { 'foo' => 'bar', 'exp' => Time.now.to_i + 1, 'nbf' => Time.now.to_i - 1 } - end - - it 'encodes and decodes JWTs' do - secret = 'secret' - jwt = JWT.encode(@payload, secret) - decoded_payload = JWT.decode(jwt, secret) - expect(decoded_payload).to include(@payload) - end - - it 'encodes and decodes JWTs for RSA signatures' do - private_key = OpenSSL::PKey::RSA.generate(512) - jwt = JWT.encode(@payload, private_key, 'RS256') - decoded_payload = JWT.decode(jwt, private_key.public_key) - expect(decoded_payload).to include(@payload) - end - - it 'encodes and decodes JWTs for ECDSA P-256 signatures' do - private_key = OpenSSL::PKey::EC.new('prime256v1') - private_key.generate_key - public_key = OpenSSL::PKey::EC.new(private_key) - public_key.private_key = nil - jwt = JWT.encode(@payload, private_key, 'ES256') - decoded_payload = JWT.decode(jwt, public_key) - expect(decoded_payload).to include(@payload) - end - - it 'encodes and decodes JWTs for ECDSA P-384 signatures' do - private_key = OpenSSL::PKey::EC.new('secp384r1') - private_key.generate_key - public_key = OpenSSL::PKey::EC.new(private_key) - public_key.private_key = nil - jwt = JWT.encode(@payload, private_key, 'ES384') - decoded_payload = JWT.decode(jwt, public_key) - expect(decoded_payload).to include(@payload) - end - - it 'encodes and decodes JWTs for ECDSA P-521 signatures' do - private_key = OpenSSL::PKey::EC.new('secp521r1') - private_key.generate_key - public_key = OpenSSL::PKey::EC.new(private_key) - public_key.private_key = nil - jwt = JWT.encode(@payload, private_key, 'ES512') - decoded_payload = JWT.decode(jwt, public_key) - expect(decoded_payload).to include(@payload) - end - - it 'encodes and decodes JWTs with custom header fields' do - private_key = OpenSSL::PKey::RSA.generate(512) - jwt = JWT.encode(@payload, private_key, 'RS256', 'kid' => 'default') - decoded_payload = JWT.decode(jwt) do |header| - expect(header['kid']).to eq('default') - private_key.public_key - end - expect(decoded_payload).to include(@payload) - end - - it 'raises encode exception when ECDSA algorithm does not match key' do - private_key = OpenSSL::PKey::EC.new('prime256v1') - private_key.generate_key - expect do - JWT.encode(@payload, private_key, 'ES512') - end.to raise_error(JWT::IncorrectAlgorithm, 'payload algorithm is ES512 but ES256 signing key was provided') - end - - it 'decodes valid JWTs' do - example_payload = { 'hello' => 'world' } - example_secret = 'secret' - example_jwt = 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJoZWxsbyI6ICJ3b3JsZCJ9.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8' - decoded_payload = JWT.decode(example_jwt, example_secret) - expect(decoded_payload).to include(example_payload) - end - - it 'decodes valid ES512 JWTs' do - example_payload = { 'hello' => 'world' } - example_jwt = 'eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJoZWxsbyI6IndvcmxkIn0.AQx1MqdTni6KuzfOoedg2-7NUiwe-b88SWbdmviz40GTwrM0Mybp1i1tVtmTSQ91oEXGXBdtwsN6yalzP9J-sp2YATX_Tv4h-BednbdSvYxZsYnUoZ--ZUdL10t7g8Yt3y9hdY_diOjIptcha6ajX8yzkDGYG42iSe3f5LywSuD6FO5c' - pubkey_pem = "-----BEGIN PUBLIC KEY-----\nMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAcpkss6wI7PPlxj3t7A1RqMH3nvL4\nL5Tzxze/XeeYZnHqxiX+gle70DlGRMqqOq+PJ6RYX7vK0PJFdiAIXlyPQq0B3KaU\ne86IvFeQSFrJdCc0K8NfiH2G1loIk3fiR+YLqlXk6FAeKtpXJKxR1pCQCAM+vBCs\nmZudf1zCUZ8/4eodlHU=\n-----END PUBLIC KEY-----" - pubkey = OpenSSL::PKey::EC.new pubkey_pem - decoded_payload = JWT.decode(example_jwt, pubkey) - expect(decoded_payload).to include(example_payload) - end - - it 'decodes valid JWTs with iss' do - example_payload = { 'hello' => 'world', 'iss' => 'jwtiss' } - example_secret = 'secret' - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaXNzIjoiand0aXNzIn0.nTZkyYfpGUyKULaj45lXw_1gXXjHvGW4h5V7okHdUqQ' - decoded_payload = JWT.decode(example_jwt, example_secret, true, 'iss' => 'jwtiss') - expect(decoded_payload).to include(example_payload) - end - - context 'issuer claim verifications' do - it 'raises invalid issuer when "iss" claim does not match' do - example_secret = 'secret' - - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaXNzIjoiand0aXNzIn0.nTZkyYfpGUyKULaj45lXw_1gXXjHvGW4h5V7okHdUqQ' - expect { JWT.decode(example_jwt, example_secret, true, verify_iss: true, iss: 'jwt_iss') }.to raise_error(JWT::InvalidIssuerError, /Expected jwt_iss, received jwtiss/) + let :payload do + { + user_id: 'some@user.tld' + } + end + + let :data do + { + :secret => 'My$ecretK3y', + :rsa_private => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-private.pem'))), + :rsa_public => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-public.pem'))), + :wrong_rsa_private => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))), + :wrong_rsa_public => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem'))), + 'ES256_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-private.pem'))), + 'ES256_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-public.pem'))), + 'ES384_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec384-private.pem'))), + 'ES384_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec384-public.pem'))), + 'ES512_private' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec512-private.pem'))), + 'ES512_public' => OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec512-public.pem'))), + 'NONE' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.', + 'HS256' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.tCGvlClld0lbQ3NZaH8y53n5RSBr3zlS4Oy5bXqvzZQ', + 'HS384' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.sj1gc01SawlJSrPZgmveifJ8CzZRYAWjejWm4FRaGaAISESJ9Ncf12fCz2vHrITm', + 'HS512' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.isjhsWMZpRQOWw6LKtlY4L6tMDNkLr0qZ3bQe_xRFXWhzVvJlkclTbLVa1J6Dlj2WyZ_I1jEobTaFMDoXPzwWg', + 'RS256' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.u82QrhjZTtwve5akvfWS_4LPywbkb1Yp0nUwZJWtTW0ID7dY9rRiQF5KGj2UDLZotqRlUjyNQgE_hB5BBzICDQdCjQHQoYWE5n_D2wV4PMu7Qg3FVKoBFbf8ee6irodu10fgYxpUIZtvbWw52_6k6A9IoSLSzx_lCcxoVGdW90dUuKhBcZkDtY5WNuQg7MiDthupSL1-V4Y1jmT_7o8tLNGFiocyZfGNw4yGpEOGNvD5WePNit0xsnbj6dEquovUvSFKsMaQXp2PVDEkLOiLMcyk0RrHqrHw2eNSCquWTH8PhX5Up-CVmjQM5zF9ibkaiq8NyPtsy-7rgtbyVMqXBQ', + 'RS384' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzM4NCJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.2_jPwOsUWJ-3r6lXMdJGPdhLNJQSSEmY2mrDXCwNJk-2YhMIqKAzJJCbyso_A1hS7BVkXmHt54RCcNJXroZBOgmGavCcYTPMaT6sCvVVvJJ_wn7jzKHNAJfL5nWeynTQIBWmL-m_v9QpZAgPALdeqjPRv4JHePZm23kvrUgQOxef2ldXv1l6IB3zfF72uEbk9T5pKBvgeeeQ46xm_HtkpXqMdqcTHawUXeXhuiWxuWfy9pAvhm8ivxwJhiQ15-sQNBlS9lG1_gQz1xaZ_Ou_n1nhNfGwpK5HeS0AgmqsqyCOvaGHeAuAOPZ_dSC3cFKu2AP7kc6_AKBgwJzh4agkXg', + 'RS512' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJ1c2VyX2lkIjoic29tZUB1c2VyLnRsZCJ9.abwof7BqTvuLkN69OhEuFTP7vjGzfvAvooQdwIRne_a88MsjCq31n4UPvyIlY9_8u69rpU79RbMsrq_UZ6L85zP83EcyYI-HOfFZgYDAL3DJ7biBD99JTzyOsH_2i_E6yCkevjEX6uL_Am_C7jpWyePJQkYzTFni6mW4W1T9UobiVGA1tIZ-XOJDPHHxZkGu6W8lKW0UCsr9Ge2SCSlTs_LDSOa34gqMC5GP89unhLqSMqEMJ_Nm6Rj0rnmk87wBZM-b04LLteWuEU59QDNa4nMTjfXW74U4hX9n5EECDPQdQMecgxlUbFunAfZaoNzP4m7H4vux2FzYkjkXhdqnnw', + 'ES256' => '', + 'ES384' => '', + 'ES512' => '' + } + end + + context 'alg: NONE' do + let :alg do + 'none' end - it 'raises invalid issuer when "iss" claim is missing in payload' do - example_secret = 'secret' + it 'should generate a valid token' do + token = JWT.encode payload, nil, alg - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIn0.bqxXg9VwcbXKoiWtp-osd0WKPX307RjcN7EuXbdq-CE' - expect { JWT.decode(example_jwt, example_secret, true, verify_iss: true, iss: 'jwt_iss') }.to raise_error(JWT::InvalidIssuerError, /received /) + expect(token).to eq data['NONE'] end - it 'does not raise invalid issuer when verify_iss is set to false (default option)' do - example_secret = 'secret' + it 'should decode a valid token' do + payload, header = JWT.decode data['NONE'] - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaXNzIjoiand0aXNzIn0.nTZkyYfpGUyKULaj45lXw_1gXXjHvGW4h5V7okHdUqQ' - expect { JWT.decode(example_jwt, example_secret, true, 'iss' => 'jwt_iss') }.not_to raise_error - end - - it 'does not raise invalid issuer when correct "iss" is in payload' do - example_secret = 'secret' - - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaXNzIjoiand0X2lzcyJ9.mwbyRJJZJR1C5lBt8WOLg0ZMuwP9VGDf5HiQtFhd-eA' - expect { JWT.decode(example_jwt, example_secret, true, :verify_iss => true, 'iss' => 'jwt_iss') }.not_to raise_error + expect(header['alg']).to eq alg + expect(payload).to eq payload end end - it 'decodes valid JWTs with iat' do - example_payload = { 'hello' => 'world', 'iat' => 1_425_917_209 } - example_secret = 'secret' - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaWF0IjoxNDI1OTE3MjA5fQ.m4F-Ugo7aLnLunBBO3BeDidyWMx8T9eoJz6FW2rgQhU' - decoded_payload = JWT.decode(example_jwt, example_secret, true, iat: true) - expect(decoded_payload).to include(example_payload) - end + %w(HS256 HS384 HS512).each do |alg| + context "alg: #{alg}" do + it 'should generate a valid token' do + token = JWT.encode payload, data[:secret], alg - it 'raises decode exception when iat is invalid' do - # example_payload = {'hello' => 'world', 'iat' => 'abc'} - example_secret = 'secret' - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaWF0IjoiMTQyNTkxNzIwOSJ9.Mn_vk61xWjIhbXFqAB0nFmNkDiCmfzUgl_LaCKRT6S8' - expect { JWT.decode(example_jwt, example_secret, true, verify_iat: true, 'iat' => 1_425_917_209) }.to raise_error(JWT::InvalidIatError) - end - - it 'raises decode exception when iat is in the future' do - invalid_payload = @payload.clone - invalid_payload['iat'] = Time.now.to_i + 3 - secret = 'secret' - jwt = JWT.encode(invalid_payload, secret) - expect { JWT.decode(jwt, secret, true, verify_iat: true) }.to raise_error(JWT::InvalidIatError) - end - - it 'performs normal decode if iat is within leeway' do - invalid_payload = @payload.clone - invalid_payload['iat'] = Time.now.to_i + 3 - secret = 'secret' - jwt = JWT.encode(invalid_payload, secret) - expect { JWT.decode(jwt, secret, true, verify_iat: true, leeway: 3) }.to_not raise_error - end - - it 'decodes valid JWTs with jti' do - example_payload = { 'hello' => 'world', 'iat' => 1_425_917_209, 'jti' => Digest::MD5.hexdigest('secret:1425917209') } - example_secret = 'secret' - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaWF0IjoxNDI1OTE3MjA5LCJqdGkiOiI1NWM3NzZlMjFmN2NiZDg3OWMwNmZhYzAxOGRhYzQwMiJ9.ET0hb-VTUOL3M22oG13ofzvGPLMAncbF8rdNDIqo8tg' - decoded_payload = JWT.decode(example_jwt, example_secret, true, 'jti' => Digest::MD5.hexdigest('secret:1425917209')) - expect(decoded_payload).to include(example_payload) - end - - it 'raises decode exception when jti is invalid' do - # example_payload = {'hello' => 'world', 'iat' => 1425917209, 'jti' => Digest::MD5.hexdigest('secret:1425917209')} - example_secret = 'secret' - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiaWF0IjoxNDI1OTE3MjA5LCJqdGkiOiI1NWM3NzZlMjFmN2NiZDg3OWMwNmZhYzAxOGRhYzQwMiJ9.ET0hb-VTUOL3M22oG13ofzvGPLMAncbF8rdNDIqo8tg' - expect { JWT.decode(example_jwt, example_secret, true, :verify_jti => true, 'jti' => Digest::MD5.hexdigest('secret:1425922032')) }.to raise_error(JWT::InvalidJtiError) - # expect{ JWT.decode(example_jwt, example_secret) }.to raise_error(JWT::InvalidJtiError) - end - - it 'raises decode exception when jti without iat' do - # example_payload = {'hello' => 'world', 'jti' => Digest::MD5.hexdigest('secret:1425917209')} - example_secret = 'secret' - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwianRpIjoiNTVjNzc2ZTIxZjdjYmQ4NzljMDZmYWMwMThkYWM0MDIifQ.n0foJCnCM_-_xUvG_TOmR9mYpL2y0UqZOD_gv33djeE' - expect { JWT.decode(example_jwt, example_secret, true, :verify_jti => true, 'jti' => Digest::MD5.hexdigest('secret:1425922032')) }.to raise_error(JWT::InvalidJtiError) - end + expect(token).to eq data[alg] + end - context 'aud claim verifications' do - it 'decodes valid JWTs with aud' do - example_payload = { 'hello' => 'world', 'aud' => 'url:pnd' } - example_payload2 = { 'hello' => 'world', 'aud' => ['url:pnd', 'aud:yes'] } - example_secret = 'secret' - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiYXVkIjoidXJsOnBuZCJ9._gT5veUtNiZD7wLEC6Gd0-nkQV3cl1z8G0zXq8qcd-8' - example_jwt2 = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiYXVkIjpbInVybDpwbmQiLCJhdWQ6eWVzIl19.qNPNcT4X9B5uI91rIwbW2bIPTsp8wbRYW3jkZkrmqbQ' - decoded_payload = JWT.decode(example_jwt, example_secret, true, :verify_aud => true, 'aud' => 'url:pnd') - decoded_payload2 = JWT.decode(example_jwt2, example_secret, true, :verify_aud => true, 'aud' => 'url:pnd') - expect(decoded_payload).to include(example_payload) - expect(decoded_payload2).to include(example_payload2) - end + it 'should decode a valid token' do + payload, header = JWT.decode data[alg], data[:secret] - it 'raises deode exception when aud is invalid' do - # example_payload = {'hello' => 'world', 'aud' => 'url:pnd'} - example_secret = 'secret' - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwiYXVkIjoidXJsOnBuZCJ9._gT5veUtNiZD7wLEC6Gd0-nkQV3cl1z8G0zXq8qcd-8' - expect { JWT.decode(example_jwt, example_secret, true, verify_aud: true, aud: 'wrong:aud') }.to raise_error(JWT::InvalidAudError) - end - - it 'raises deode exception when aud is missing' do - # JWT.encode('hello' => 'world', 'secret') - example_secret = 'secret' - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIn0.bqxXg9VwcbXKoiWtp-osd0WKPX307RjcN7EuXbdq-CE' - expect { JWT.decode(example_jwt, example_secret, true, verify_aud: true, aud: 'url:pnd') }.to raise_error(JWT::InvalidAudError) + expect(header['alg']).to eq alg + expect(payload).to eq payload + end end end - it 'decodes valid JWTs with sub' do - example_payload = { 'hello' => 'world', 'sub' => 'subject' } - example_secret = 'secret' - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJoZWxsbyI6IndvcmxkIiwic3ViIjoic3ViamVjdCJ9.QUnNVZm4SPB4vP2zY9m1LoUSOx-5oGXBhj7R89D_UtA' - decoded_payload = JWT.decode(example_jwt, example_secret, true, 'sub' => 'subject') - expect(decoded_payload).to include(example_payload) - end - - it 'raises decode exception when verify_sub is set but the JWT does not contain a sub' do - example_payload = {'foo' => 'bar'} - example_secret = 'secret' - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIifQ.bVhBeMrW5g33Vi4FLSLn7aqcmAiupmmw-AY17YxCYLI' - expect { JWT.decode(example_jwt, example_secret, true, verify_sub: true, sub: 'subject') }.to raise_error(JWT::InvalidSubError) - end - - it 'raise decode exception when the sub does not match' do - example_payload = {'sub' => 'subject', 'foo' => 'bar'} - example_secret = 'secret' - example_jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiZm9vIjoiYmFyIn0.RUkJZgPcK3eOU3iR301nsZa3MSA936fgu03_UoamVuo' - expect { JWT.decode(example_jwt, example_secret, true, verify_sub: true, sub: 'another_subject') }.to raise_error(JWT::InvalidSubError) - end - - it 'raises decode exception when the token is invalid' do - example_secret = 'secret' - # Same as above exmaple with some random bytes replaced - example_jwt = 'eyJhbGciOiAiSFMyNTYiLCAidHiMomlwIjogIkJ9.eyJoZWxsbyI6ICJ3b3JsZCJ9.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8' - expect { JWT.decode(example_jwt, example_secret) }.to raise_error(JWT::DecodeError) - end - - it 'raises verification exception with wrong hmac key' do - right_secret = 'foo' - bad_secret = 'bar' - jwt_message = JWT.encode(@payload, right_secret, 'HS256') - expect { JWT.decode(jwt_message, bad_secret) }.to raise_error(JWT::VerificationError) - end - - it 'raises decode exception when ECDSA algorithm does not match key' do - right_private_key = OpenSSL::PKey::EC.new('prime256v1') - right_private_key.generate_key - right_public_key = OpenSSL::PKey::EC.new(right_private_key) - right_public_key.private_key = nil - bad_private_key = OpenSSL::PKey::EC.new('secp384r1') - bad_private_key.generate_key - bad_public_key = OpenSSL::PKey::EC.new(bad_private_key) - bad_public_key.private_key = nil - jwt = JWT.encode(@payload, right_private_key, 'ES256') - expect do - JWT.decode(jwt, bad_public_key) - end.to raise_error(JWT::IncorrectAlgorithm, 'payload algorithm is ES256 but ES384 verification key was provided') - end + %w(RS256 RS384 RS512).each do |alg| + context "alg: #{alg}" do + it 'should generate a valid token' do + token = JWT.encode payload, data[:rsa_private], alg - it 'raises verification exception with wrong rsa key' do - right_private_key = OpenSSL::PKey::RSA.generate(512) - bad_private_key = OpenSSL::PKey::RSA.generate(512) - jwt = JWT.encode(@payload, right_private_key, 'RS256') - expect { JWT.decode(jwt, bad_private_key.public_key) }.to raise_error(JWT::VerificationError) - end - - it 'raises verification exception with wrong ECDSA key' do - right_private_key = OpenSSL::PKey::EC.new('prime256v1') - right_private_key.generate_key - bad_private_key = OpenSSL::PKey::EC.new('prime256v1') - bad_private_key.generate_key - bad_public_key = OpenSSL::PKey::EC.new(bad_private_key) - bad_public_key.private_key = nil - jwt = JWT.encode(@payload, right_private_key, 'ES256') - expect { JWT.decode(jwt, bad_public_key) }.to raise_error(JWT::VerificationError) - end - - it 'raises decode exception with invalid signature' do - example_secret = 'secret' - example_jwt = 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJoZWxsbyI6ICJ3b3JsZCJ9.' - expect { JWT.decode(example_jwt, example_secret) }.to raise_error(JWT::DecodeError) - end - - it 'raises decode exception with nonexistent header' do - expect { JWT.decode('..stuff') }.to raise_error(JWT::DecodeError) - end - - it 'raises decode exception with nonexistent payload' do - expect { JWT.decode('eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9..stuff') }.to raise_error(JWT::DecodeError) - end - - it 'raises decode exception with nil jwt' do - expect { JWT.decode(nil) }.to raise_error(JWT::DecodeError) - end + expect(token).to eq data[alg] + end - it 'allows decoding without key' do - right_secret = 'foo' - bad_secret = 'bar' - jwt = JWT.encode(@payload, right_secret) - decoded_payload = JWT.decode(jwt, bad_secret, false) - expect(decoded_payload).to include(@payload) - end + it 'should decode a valid token' do + payload, header = JWT.decode data[alg], data[:rsa_public] - it 'checks the key when verify is truthy' do - right_secret = 'foo' - bad_secret = 'bar' - jwt = JWT.encode(@payload, right_secret) - verify = 'yes' =~ /^y/i - expect { JWT.decode(jwt, bad_secret, verify) }.to raise_error(JWT::DecodeError) - end - - it 'raises exception on unsupported crypto algorithm' do - expect { JWT.encode(@payload, 'secret', 'HS1024') }.to raise_error(NotImplementedError) + expect(header['alg']).to eq alg + expect(payload).to eq payload + end + end end - it 'raises exception when decoded with a different algorithm than it was encoded with' do - jwt = JWT.encode(@payload, 'foo', 'HS384') - expect { JWT.decode(jwt, 'foo', true, algorithm: 'HS512') }.to raise_error(JWT::IncorrectAlgorithm) - end + %w(ES256 ES384 ES512).each do |alg| + context "alg: #{alg}" do + it 'should generate a valid token' do + data[alg] = JWT.encode payload, data["#{alg}_private"], alg + payload, header = JWT.decode data[alg], data["#{alg}_public"] - it 'does not raise exception when encoded with the expected algorithm' do - jwt = JWT.encode(@payload, 'foo', 'HS512') - JWT.decode(jwt, 'foo', true, algorithm: 'HS512') - end + expect(header['alg']).to eq alg + expect(payload).to eq payload + end - it 'encodes and decodes plaintext JWTs' do - jwt = JWT.encode(@payload, nil, nil) - expect(jwt.split('.').length).to eq(2) - decoded_payload = JWT.decode(jwt, nil, nil) - expect(decoded_payload).to include(@payload) - end + it 'should decode a valid token' do + data[alg] = JWT.encode payload, data["#{alg}_private"], alg + payload, header = JWT.decode data[alg], data["#{alg}_public"] - it 'requires a signature segment when verify is truthy' do - jwt = JWT.encode(@payload, nil, nil) - expect(jwt.split('.').length).to eq(2) - expect { JWT.decode(jwt, nil, true) }.to raise_error(JWT::DecodeError) + expect(header['alg']).to eq alg + expect(payload).to eq payload + end + end end - it 'does not use == to compare digests' do - secret = 'secret' - jwt = JWT.encode(@payload, secret) - crypto_segment = jwt.split('.').last - - signature = JWT.base64url_decode(crypto_segment) - expect(signature).not_to receive('==') - expect(JWT).to receive(:base64url_decode).with(crypto_segment).once.and_return(signature) - expect(JWT).to receive(:base64url_decode).at_least(:once).and_call_original + context 'Invalid' do + it 'algorithm should raise NotImplementedError' do + expect do + JWT.encode payload, 'secret', 'HS255' + end.to raise_error NotImplementedError + end - JWT.decode(jwt, secret) - end + it 'ECDSA curve_name should raise JWT::IncorrectAlgorithm' do + key = OpenSSL::PKey::EC.new 'secp256k1' + key.generate_key - it 'raises error when expired' do - expired_payload = @payload.clone - expired_payload['exp'] = Time.now.to_i - 1 - secret = 'secret' - jwt = JWT.encode(expired_payload, secret) - expect { JWT.decode(jwt, secret) }.to raise_error(JWT::ExpiredSignature) - end + expect do + JWT.encode payload, key, 'ES256' + end.to raise_error JWT::IncorrectAlgorithm - it 'raise ExpiredSignature even when exp claims is a string' do - expired_payload = @payload.clone - expired_payload['exp'] = (Time.now.to_i).to_s - secret = 'secret' - jwt = JWT.encode(expired_payload, secret) - expect { JWT.decode(jwt, secret) }.to raise_error(JWT::ExpiredSignature) - end + token = JWT.encode payload, data['ES256_private'], 'ES256' + key.private_key = nil - it 'performs normal decode with skipped expiration check' do - expired_payload = @payload.clone - expired_payload['exp'] = Time.now.to_i - 1 - secret = 'secret' - jwt = JWT.encode(expired_payload, secret) - decoded_payload = JWT.decode(jwt, secret, true, verify_expiration: false) - expect(decoded_payload).to include(expired_payload) + expect do + JWT.decode token, key + end.to raise_error JWT::IncorrectAlgorithm + end end - it 'performs normal decode using leeway' do - expired_payload = @payload.clone - expired_payload['exp'] = Time.now.to_i - 2 - secret = 'secret' - jwt = JWT.encode(expired_payload, secret) - decoded_payload = JWT.decode(jwt, secret, true, leeway: 3) - expect(decoded_payload).to include(expired_payload) - end + context 'Verify' do + context 'algorithm' do + it 'should raise JWT::IncorrectAlgorithm on missmatch' do + token = JWT.encode payload, data[:secret], 'HS512' - it 'raises error when before nbf' do - immature_payload = @payload.clone - immature_payload['nbf'] = Time.now.to_i + 1 - secret = 'secret' - jwt = JWT.encode(immature_payload, secret) - expect { JWT.decode(jwt, secret) }.to raise_error(JWT::ImmatureSignature) - end + expect do + JWT.decode token, data[:secret], true, algorithm: 'HS384' + end.to raise_error JWT::IncorrectAlgorithm - it 'doesnt raise error when equal to nbf' do - mature_payload = @payload.clone - mature_payload['nbf'] = Time.now.to_i - secret = 'secret' - jwt = JWT.encode(mature_payload, secret) - decoded_payload = JWT.decode(jwt, secret, true, verify_expiration: false) - expect(decoded_payload).to include(mature_payload) - end + expect do + JWT.decode token, data[:secret], true, algorithm: 'HS512' + end.not_to raise_error + end + end - it 'doesnt raise error when after nbf' do - mature_payload = @payload.clone - secret = 'secret' - jwt = JWT.encode(mature_payload, secret) - decoded_payload = JWT.decode(jwt, secret, true, verify_expiration: false) - expect(decoded_payload).to include(mature_payload) - end + context 'expiration claim' do + let :exp do + Time.now.to_i - 5 + end - it 'raise ImmatureSignature even when nbf claim is a string' do - immature_payload = @payload.clone - immature_payload['nbf'] = (Time.now.to_i + 1).to_s - secret = 'secret' - jwt = JWT.encode(immature_payload, secret) - expect { JWT.decode(jwt, secret) }.to raise_error(JWT::ImmatureSignature) - end + let :leeway do + 10 + end - it 'performs normal decode with skipped not before check' do - immature_payload = @payload.clone - immature_payload['nbf'] = Time.now.to_i + 2 - secret = 'secret' - jwt = JWT.encode(immature_payload, secret) - decoded_payload = JWT.decode(jwt, secret, true, verify_not_before: false) - expect(decoded_payload).to include(immature_payload) - end + let :token do + payload.merge!(exp: exp) - it 'performs normal decode using leeway' do - immature_payload = @payload.clone - immature_payload['nbf'] = Time.now.to_i - 2 - secret = 'secret' - jwt = JWT.encode(immature_payload, secret) - decoded_payload = JWT.decode(jwt, secret, true, leeway: 3) - expect(decoded_payload).to include(immature_payload) - end + JWT.encode payload, data[:secret] + end - describe 'secure comparison' do - it 'returns true if strings are equal' do - expect(JWT.secure_compare('Foo', 'Foo')).to be true - end + it 'old token should raise JWT::ExpiredSignature' do + expect do + JWT.decode token, data[:secret] + end.to raise_error JWT::ExpiredSignature + end - it 'returns false if either input is nil or empty' do - [nil, ''].each do |bad| - expect(JWT.secure_compare(bad, 'Foo')).to be false - expect(JWT.secure_compare('Foo', bad)).to be false + it 'should handle leeway' do + expect do + JWT.decode token, data[:secret], true, leeway: leeway + end.not_to raise_error end end - it 'retuns false if the strings are different' do - expect(JWT.secure_compare('Foo', 'Bar')).to be false - end - end + context 'not before claim' do + let :nbf do + Time.now.to_i + 5 + end - # no method should leave OpenSSL.errors populated - after do - expect(OpenSSL.errors).to be_empty - end + let :leeway do + 10 + end - it 'raise exception on invalid signature' do - pubkey = OpenSSL::PKey::RSA.new(<<-PUBKEY) ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCaY7425h964bjaoLeUm -SlZ8sK7VtVk9zHbGmZh2ygGYwfuUf2bmMye2Ofv99yDE/rd4loVIAcu7RVvDRgHq -3/CZTnIrSvHsiJQsHBNa3d+F1ihPfzURzf1M5k7CFReBj2SBXhDXd57oRfBQj12w -CVhhwP6kGTAWuoppbIIIBfNF2lE/Nvm7lVVYQqL9xOrP/AQ4xRbpQlB8Ll9sO9Or -SvbWhCDa/LMOWxHdmrcJi6XoSg1vnOyCoKbyAoauTt/XqdkHbkDdQ6HFbJieu9il -LDZZNliPhfENuKeC2MCGVXTEu8Cqhy1w6e4axavLlXoYf4laJIZ/e7au8SqDbY0B -xwIDAQAB ------END PUBLIC KEY----- -PUBKEY - jwt = ( - 'eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiY' \ - 'XVkIjoiMTA2MDM1Nzg5MTY4OC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSI' \ - 'sImNpZCI6IjEwNjAzNTc4OTE2ODguYXBwcy5nb29nbGV1c2VyY29udGVudC5jb' \ - '20iLCJpZCI6IjExNjQ1MjgyNDMwOTg1Njc4MjE2MyIsInRva2VuX2hhc2giOiJ' \ - '0Z2hEOUo4bjhWME4ydmN3NmVNaWpnIiwiaWF0IjoxMzIwNjcwOTc4LCJleHAiO' \ - 'jEzMjA2NzQ4Nzh9.D8x_wirkxDElqKdJBcsIws3Ogesk38okz6MN7zqC7nEAA7' \ - 'wcy1PxsROY1fmBvXSer0IQesAqOW-rPOCNReSn-eY8d53ph1x2HAF-AzEi3GOl' \ - '6hFycH8wj7Su6JqqyEbIVLxE7q7DkAZGaMPkxbTHs1EhSd5_oaKQ6O4xO3ZnnT4' - ) - expect { JWT.decode(jwt, pubkey, true) }.to raise_error(JWT::DecodeError) - end + let :token do + payload.merge!(nbf: nbf) - describe 'urlsafe base64 encoding' do - it 'replaces + and / with - and _' do - allow(Base64).to receive(:encode64) { 'string+with/non+url-safe/characters_' } - expect(JWT.base64url_encode('foo')).to eq('string-with_non-url-safe_characters_') - end - end + JWT.encode payload, data[:secret] + end - describe 'decoded_segments' do - it 'allows access to the decoded header and payload' do - secret = 'secret' - jwt = JWT.encode(@payload, secret) - decoded_segments = JWT.decoded_segments(jwt) - expect(decoded_segments.size).to eq(4) - expect(decoded_segments[0]).to eq('typ' => 'JWT', 'alg' => 'HS256') - expect(decoded_segments[1]).to eq(@payload) + it 'future token should raise JWT::ImmatureSignature' do + expect do + JWT.decode token, data[:secret] + end.to raise_error JWT::ImmatureSignature + end + it 'should handle leeway' do + expect do + JWT.decode token, data[:secret], true, leeway: leeway + end.not_to raise_error + end end end end From 8ef680aa877db4bc2eed33fdcb118919f8e1e5b6 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Wed, 13 May 2015 12:22:23 +0200 Subject: [PATCH 05/23] Add more specs --- spec/jwt_spec.rb | 78 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index 41b040ad..340f4bd7 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -34,6 +34,10 @@ } end + after(:each) do + expect(OpenSSL.errors).to be_empty + end + context 'alg: NONE' do let :alg do 'none' @@ -67,6 +71,18 @@ expect(header['alg']).to eq alg expect(payload).to eq payload end + + it 'wrong secret should raise JWT::DecodeError' do + expect do + JWT.decode data[alg], 'wrong_secret' + end.to raise_error JWT::DecodeError + end + + it 'wrong secret and verify = false should not raise JWT::DecodeError' do + expect do + JWT.decode data[alg], 'wrong_secret', false + end.not_to raise_error + end end end @@ -84,13 +100,36 @@ expect(header['alg']).to eq alg expect(payload).to eq payload end + + it 'wrong key should raise JWT::DecodeError' do + key = OpenSSL::PKey.read File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem')) + + expect do + JWT.decode data[alg], key + end.to raise_error JWT::DecodeError + end + + it 'wrong key and verify = false should not raise JWT::DecodeError' do + key = OpenSSL::PKey.read File.read(File.join(CERT_PATH, 'rsa-2048-wrong-public.pem')) + + expect do + JWT.decode data[alg], key, false + end.not_to raise_error + end end end %w(ES256 ES384 ES512).each do |alg| context "alg: #{alg}" do - it 'should generate a valid token' do + before(:each) do data[alg] = JWT.encode payload, data["#{alg}_private"], alg + end + + let :wrong_key do + OpenSSL::PKey.read File.read(File.join(CERT_PATH, 'ec256-wrong-public.pem')) + end + + it 'should generate a valid token' do payload, header = JWT.decode data[alg], data["#{alg}_public"] expect(header['alg']).to eq alg @@ -98,12 +137,23 @@ end it 'should decode a valid token' do - data[alg] = JWT.encode payload, data["#{alg}_private"], alg payload, header = JWT.decode data[alg], data["#{alg}_public"] expect(header['alg']).to eq alg expect(payload).to eq payload end + + it 'wrong key should raise JWT::DecodeError' do + expect do + JWT.decode data[alg], wrong_key + end.to raise_error JWT::DecodeError + end + + it 'wrong key and verify = false should not raise JWT::DecodeError' do + expect do + JWT.decode data[alg], wrong_key, false + end.not_to raise_error + end end end @@ -201,4 +251,28 @@ end end end + + context 'Base64' do + it 'urlsafe replace + / with - _' do + allow(Base64).to receive(:encode64) { 'string+with/non+url-safe/characters_' } + expect(JWT.base64url_encode('foo')).to eq('string-with_non-url-safe_characters_') + end + end + + describe 'secure comparison' do + it 'returns true if strings are equal' do + expect(JWT.secure_compare('Foo', 'Foo')).to eq true + end + + it 'returns false if either input is nil or empty' do + [nil, ''].each do |bad| + expect(JWT.secure_compare(bad, 'Foo')).to eq false + expect(JWT.secure_compare('Foo', bad)).to eq false + end + end + + it 'retuns false if the strings are different' do + expect(JWT.secure_compare('Foo', 'Bar')).to eq false + end + end end From 1a89c8e11f09f545fb20dd8f7677cf2244b1bed1 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Wed, 3 Jun 2015 16:36:12 +0200 Subject: [PATCH 06/23] Update tests and lib Remove 'NONE' fix Add more tests for verifications Copy paste new verification code from master --- lib/jwt.rb | 2 -- spec/jwt_spec.rb | 52 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/lib/jwt.rb b/lib/jwt.rb index ab5474b3..b8272da9 100644 --- a/lib/jwt.rb +++ b/lib/jwt.rb @@ -1,5 +1,3 @@ -# encoding: utf-8 - require 'base64' require 'openssl' require 'jwt/json' diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index 340f4bd7..3a65fa10 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -50,7 +50,7 @@ end it 'should decode a valid token' do - payload, header = JWT.decode data['NONE'] + payload, header = JWT.decode data['NONE'], nil, false expect(header['alg']).to eq alg expect(payload).to eq payload @@ -244,12 +244,62 @@ JWT.decode token, data[:secret] end.to raise_error JWT::ImmatureSignature end + it 'should handle leeway' do expect do JWT.decode token, data[:secret], true, leeway: leeway end.not_to raise_error end end + + context 'issuer claim' do + let :iss do + 'ruby-jwt-gem' + end + + let :token do + iss_payload = payload.merge({ + iss: iss + }) + + JWT.encode iss_payload, data[:secret] + end + + let :invalid_token do + JWT.encode payload, data[:secret] + end + + it 'invalid iss should raise JWT::InvalidIssuerError' do + expect do + JWT.decode token, data[:secret], true, { + 'iss' => 'wrong-issuer', + :verify_iss => true + } + end.to raise_error JWT::InvalidIssuerError + end + + it 'valid iss should not raise JWT::InvalidIssuerError' do + expect do + JWT.decode token, data[:secret], true, { + 'iss' => iss, + :verify_iss => true + } + end.not_to raise_error + end + end + + context 'issued at claim' do + + end + + context 'audience claim' do + end + + context 'subject claim' do + end + + context 'jwt id claim' do + end end context 'Base64' do From 4dfbbe130a939f9f0c131752fbaeb917209c9088 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Wed, 3 Jun 2015 20:00:25 +0200 Subject: [PATCH 07/23] Add pending test, implement iat specs --- spec/jwt_spec.rb | 54 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index 3a65fa10..2cd95f6d 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -259,7 +259,7 @@ let :token do iss_payload = payload.merge({ - iss: iss + :iss => iss }) JWT.encode iss_payload, data[:secret] @@ -289,16 +289,68 @@ end context 'issued at claim' do + let :iat do + Time.now.to_i + end + + let :new_payload do + payload.merge({ + :iat => iat + }) + end + + let :token do + JWT.encode new_payload, data[:secret] + end + + let :invalid_token do + JWT.encode new_payload.merge({ 'iat' => iat + 60 }), data[:secret] + end + + let :leeway do + 30 + end + it 'invalid iat should raise JWT::InvalidIatError' do + expect do + JWT.decode invalid_token, data[:secret], true, { + :verify_iat => true + } + end.to raise_error JWT::InvalidIatError + end + + it 'should ignore leeway' do + expect do + JWT.decode invalid_token, data[:secret], true, { + :verify_iat => true, + :leeway => 70 + } + end.to raise_error JWT::InvalidIatError + end + + it 'valid iat should not raise JWT::InvalidIatError' do + expect do + JWT.decode token, data[:secret], true, { + :verify_iat => true + } + end.to_not raise_error + end end context 'audience claim' do + it 'invalid aud should raise JWT::InvalidAudError' + it 'valid aud should not raise JWT::InvalidAudError' + it 'should work with arrays' end context 'subject claim' do + it 'invalid sub should raise JWT::InvalidSubError' + it 'valid sub should not raise JWT::InvalidSubError' end context 'jwt id claim' do + it 'invalid jit should raise JWT::InvalidJtiError' + it 'valid jit should not raise JWT::InvalidJtiError' end end From 4d8e6744e6d7fa71f1aa321676303910729a764d Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Wed, 3 Jun 2015 20:12:34 +0200 Subject: [PATCH 08/23] Add aud verification specs --- spec/jwt_spec.rb | 58 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index 2cd95f6d..1eabf85c 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -338,9 +338,61 @@ end context 'audience claim' do - it 'invalid aud should raise JWT::InvalidAudError' - it 'valid aud should not raise JWT::InvalidAudError' - it 'should work with arrays' + let :simple_aud do + 'ruby-jwt-audience' + end + + let :array_aud do + %w(ruby-jwt-aud test-aud ruby-ruby-ruby) + end + + let :simple_token do + new_payload = payload.merge({ + 'aud' => simple_aud + }) + + JWT.encode new_payload, data[:secret] + end + + let :array_token do + new_payload = payload.merge({ + 'aud' => array_aud + }) + + JWT.encode new_payload, data[:secret] + end + + it 'invalid aud should raise JWT::InvalidAudError' do + expect do + JWT.decode simple_token, data[:secret], true, { + 'aud' => 'wrong audience', + :verify_aud => true + } + end.to raise_error JWT::InvalidAudError + + expect do + JWT.decode array_token, data[:secret], true, { + 'aud' => %w(wrong audience), + :verify_aud => true + } + end.to raise_error JWT::InvalidAudError + end + + it 'valid aud should not raise JWT::InvalidAudError' do + expect do + JWT.decode simple_token, data[:secret], true, { + 'aud' => simple_aud, + :verify_aud => true + } + end.to_not raise_error + + expect do + JWT.decode array_token, data[:secret], true, { + 'aud' => array_aud.first, + :verify_aud => true + } + end.to_not raise_error + end end context 'subject claim' do From c91e50e339854813c994bd938b0218a6eee55b89 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Wed, 3 Jun 2015 20:22:56 +0200 Subject: [PATCH 09/23] Add sub verification specs --- spec/jwt_spec.rb | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index 1eabf85c..9afdf05d 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -396,8 +396,43 @@ end context 'subject claim' do - it 'invalid sub should raise JWT::InvalidSubError' - it 'valid sub should not raise JWT::InvalidSubError' + let :sub do + 'ruby jwt subject' + end + + let :token do + new_payload = payload.merge({ + 'sub' => sub + }) + + JWT.encode new_payload, data[:secret] + end + + let :invalid_token do + new_payload = payload.merge({ + 'sub' => 'we are not the druids you are looking for' + }) + + JWT.encode new_payload, data[:secret] + end + + it 'invalid sub should raise JWT::InvalidSubError' do + expect do + JWT.decode invalid_token, data[:secret], true, { + 'sub' => sub, + :verify_sub => true + } + end.to raise_error JWT::InvalidSubError + end + + it 'valid sub should not raise JWT::InvalidSubError' do + expect do + JWT.decode token, data[:secret], true, { + 'sub' => sub, + :verify_sub => true + } + end.to_not raise_error + end end context 'jwt id claim' do From ead0d8c907633b6314962c4a9353502d1ba55191 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Wed, 10 Jun 2015 20:54:10 +0200 Subject: [PATCH 10/23] Add .rspec config file --- .rspec | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .rspec diff --git a/.rspec b/.rspec new file mode 100644 index 00000000..5d2ee7d9 --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--color +--format d \ No newline at end of file From fa11eaa19a79cced9c2a008c525faeb6707a0f18 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Wed, 10 Jun 2015 22:00:41 +0200 Subject: [PATCH 11/23] Add jti spec --- spec/jwt_spec.rb | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index 9afdf05d..5721c42d 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -435,9 +435,40 @@ end end - context 'jwt id claim' do - it 'invalid jit should raise JWT::InvalidJtiError' - it 'valid jit should not raise JWT::InvalidJtiError' + context 'jwt id claim', :focus do + let :jti do + new_payload = payload.merge({ + 'iat' => Time.now.to_i + }) + + key = data[:secret] + + new_payload.merge({ + 'jti' => Digest::MD5.hexdigest("#{key}:#{new_payload['iat']}") + }) + end + + let :token do + JWT.encode jti, data[:secret] + end + + let :invalid_token do + jti.delete('iat') + + JWT.encode jti, data[:secret] + end + + it 'invalid jti should raise JWT::InvalidJtiError' do + expect do + JWT.decode invalid_token, data[:secret], true, { :verify_jti => true, 'jti' => jti['jti'] } + end.to raise_error JWT::InvalidJtiError + end + + it 'valid jti should not raise JWT::InvalidJtiError' do + expect do + JWT.decode token, data[:secret], true, { :verify_jti => true, 'jti' => jti['jti'] } + end.to_not raise_error + end end end From e8c61c2224b1f8133d747e844ce5274c686880b9 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Wed, 10 Jun 2015 22:01:18 +0200 Subject: [PATCH 12/23] Remove :focus from specs --- spec/jwt_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index 5721c42d..b2d211d6 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -435,7 +435,7 @@ end end - context 'jwt id claim', :focus do + context 'jwt id claim' do let :jti do new_payload = payload.merge({ 'iat' => Time.now.to_i From 7d887a65e648690631ee9d1124f7cee184d7cbc9 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Tue, 28 Jul 2015 18:39:17 +0200 Subject: [PATCH 13/23] Update hash style syntax --- spec/jwt_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index b2d211d6..845a5809 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -4,7 +4,7 @@ describe JWT do let :payload do { - user_id: 'some@user.tld' + :user_id => 'some@user.tld' } end From 19a147455e633d0327e3c1817e0d9884a095e8bc Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Tue, 28 Jul 2015 18:48:16 +0200 Subject: [PATCH 14/23] Fix tests Comparing payloads now the right way Payload hash key is always a string due to JSON en/de-coding --- spec/jwt_spec.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index 845a5809..cff11663 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -4,7 +4,7 @@ describe JWT do let :payload do { - :user_id => 'some@user.tld' + 'user_id' => 'some@user.tld' } end @@ -50,10 +50,10 @@ end it 'should decode a valid token' do - payload, header = JWT.decode data['NONE'], nil, false + jwt_payload, header = JWT.decode data['NONE'], nil, false expect(header['alg']).to eq alg - expect(payload).to eq payload + expect(jwt_payload).to eq payload end end @@ -66,10 +66,10 @@ end it 'should decode a valid token' do - payload, header = JWT.decode data[alg], data[:secret] + jwt_payload, header = JWT.decode data[alg], data[:secret] expect(header['alg']).to eq alg - expect(payload).to eq payload + expect(jwt_payload).to eq payload end it 'wrong secret should raise JWT::DecodeError' do @@ -95,10 +95,10 @@ end it 'should decode a valid token' do - payload, header = JWT.decode data[alg], data[:rsa_public] + jwt_payload, header = JWT.decode data[alg], data[:rsa_public] expect(header['alg']).to eq alg - expect(payload).to eq payload + expect(jwt_payload).to eq payload end it 'wrong key should raise JWT::DecodeError' do @@ -130,17 +130,17 @@ end it 'should generate a valid token' do - payload, header = JWT.decode data[alg], data["#{alg}_public"] + jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"] expect(header['alg']).to eq alg - expect(payload).to eq payload + expect(jwt_payload).to eq payload end it 'should decode a valid token' do - payload, header = JWT.decode data[alg], data["#{alg}_public"] + jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"] expect(header['alg']).to eq alg - expect(payload).to eq payload + expect(jwt_payload).to eq payload end it 'wrong key should raise JWT::DecodeError' do From 5ce71c7cee0b4cadcd7dffc1c54a4aa3e72e0dab Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Tue, 28 Jul 2015 19:37:47 +0200 Subject: [PATCH 15/23] Update :let blocks --- spec/jwt_spec.rb | 119 ++++++++++------------------------------------- 1 file changed, 25 insertions(+), 94 deletions(-) diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index cff11663..0b0ea741 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -2,11 +2,7 @@ require 'jwt' describe JWT do - let :payload do - { - 'user_id' => 'some@user.tld' - } - end + let(:payload) { { 'user_id' => 'some@user.tld' } } let :data do { @@ -39,9 +35,7 @@ end context 'alg: NONE' do - let :alg do - 'none' - end + let(:alg) { 'none' } it 'should generate a valid token' do token = JWT.encode payload, nil, alg @@ -125,9 +119,7 @@ data[alg] = JWT.encode payload, data["#{alg}_private"], alg end - let :wrong_key do - OpenSSL::PKey.read File.read(File.join(CERT_PATH, 'ec256-wrong-public.pem')) - end + let(:wrong_key) { OpenSSL::PKey.read(File.read(File.join(CERT_PATH, 'ec256-wrong-public.pem'))) } it 'should generate a valid token' do jwt_payload, header = JWT.decode data[alg], data["#{alg}_public"] @@ -197,13 +189,8 @@ end context 'expiration claim' do - let :exp do - Time.now.to_i - 5 - end - - let :leeway do - 10 - end + let(:exp) { Time.now.to_i - 5 } + let(:leeway) { 10 } let :token do payload.merge!(exp: exp) @@ -225,13 +212,8 @@ end context 'not before claim' do - let :nbf do - Time.now.to_i + 5 - end - - let :leeway do - 10 - end + let(:nbf) { Time.now.to_i + 5 } + let(:leeway) { 10 } let :token do payload.merge!(nbf: nbf) @@ -253,21 +235,14 @@ end context 'issuer claim' do - let :iss do - 'ruby-jwt-gem' - end + let(:iss) { 'ruby-jwt-gem' } + let(:invalid_token) { JWT.encode payload, data[:secret] } let :token do - iss_payload = payload.merge({ - :iss => iss - }) - + iss_payload = payload.merge({ :iss => iss }) JWT.encode iss_payload, data[:secret] end - let :invalid_token do - JWT.encode payload, data[:secret] - end it 'invalid iss should raise JWT::InvalidIssuerError' do expect do @@ -289,27 +264,11 @@ end context 'issued at claim' do - let :iat do - Time.now.to_i - end - - let :new_payload do - payload.merge({ - :iat => iat - }) - end - - let :token do - JWT.encode new_payload, data[:secret] - end - - let :invalid_token do - JWT.encode new_payload.merge({ 'iat' => iat + 60 }), data[:secret] - end - - let :leeway do - 30 - end + let(:iat) { Time.now.to_i } + let(:new_payload) { payload.merge({ :iat => iat }) } + let(:token) { JWT.encode new_payload, data[:secret] } + let(:invalid_token) { JWT.encode new_payload.merge({ 'iat' => iat + 60 }), data[:secret] } + let(:leeway) { 30 } it 'invalid iat should raise JWT::InvalidIatError' do expect do @@ -338,27 +297,16 @@ end context 'audience claim' do - let :simple_aud do - 'ruby-jwt-audience' - end - - let :array_aud do - %w(ruby-jwt-aud test-aud ruby-ruby-ruby) - end + let(:simple_aud) { 'ruby-jwt-audience' } + let(:array_aud) { %w(ruby-jwt-aud test-aud ruby-ruby-ruby) } let :simple_token do - new_payload = payload.merge({ - 'aud' => simple_aud - }) - + new_payload = payload.merge({ 'aud' => simple_aud }) JWT.encode new_payload, data[:secret] end let :array_token do - new_payload = payload.merge({ - 'aud' => array_aud - }) - + new_payload = payload.merge({ 'aud' => array_aud }) JWT.encode new_payload, data[:secret] end @@ -396,23 +344,15 @@ end context 'subject claim' do - let :sub do - 'ruby jwt subject' - end + let(:sub) { 'ruby jwt subject' } let :token do - new_payload = payload.merge({ - 'sub' => sub - }) - + new_payload = payload.merge({ 'sub' => sub }) JWT.encode new_payload, data[:secret] end let :invalid_token do - new_payload = payload.merge({ - 'sub' => 'we are not the druids you are looking for' - }) - + new_payload = payload.merge({ 'sub' => 'we are not the druids you are looking for' }) JWT.encode new_payload, data[:secret] end @@ -437,24 +377,15 @@ context 'jwt id claim' do let :jti do - new_payload = payload.merge({ - 'iat' => Time.now.to_i - }) - + new_payload = payload.merge({ 'iat' => Time.now.to_i }) key = data[:secret] - - new_payload.merge({ - 'jti' => Digest::MD5.hexdigest("#{key}:#{new_payload['iat']}") - }) + new_payload.merge({ 'jti' => Digest::MD5.hexdigest("#{key}:#{new_payload['iat']}") }) end - let :token do - JWT.encode jti, data[:secret] - end + let(:token) { JWT.encode jti, data[:secret] } let :invalid_token do jti.delete('iat') - JWT.encode jti, data[:secret] end From 832a71629bb999cee1e13a49780085e402feaf59 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Tue, 28 Jul 2015 19:44:14 +0200 Subject: [PATCH 16/23] Remove that empty line! --- spec/jwt_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index 0b0ea741..c8a9ee30 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -243,7 +243,6 @@ JWT.encode iss_payload, data[:secret] end - it 'invalid iss should raise JWT::InvalidIssuerError' do expect do JWT.decode token, data[:secret], true, { From 9e131ca905dfbb15c3bf41b8c75ed5d36a1272e1 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Sun, 20 Sep 2015 01:48:21 +0200 Subject: [PATCH 17/23] Merge master branch changes Update code Fix broken tests --- lib/jwt.rb | 2 ++ spec/jwt_spec.rb | 79 +++++++++++++++--------------------------------- 2 files changed, 26 insertions(+), 55 deletions(-) diff --git a/lib/jwt.rb b/lib/jwt.rb index b8272da9..ab5474b3 100644 --- a/lib/jwt.rb +++ b/lib/jwt.rb @@ -1,3 +1,5 @@ +# encoding: utf-8 + require 'base64' require 'openssl' require 'jwt/json' diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index c8a9ee30..14330436 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -239,58 +239,45 @@ let(:invalid_token) { JWT.encode payload, data[:secret] } let :token do - iss_payload = payload.merge({ :iss => iss }) + iss_payload = payload.merge(iss: iss) JWT.encode iss_payload, data[:secret] end it 'invalid iss should raise JWT::InvalidIssuerError' do expect do - JWT.decode token, data[:secret], true, { - 'iss' => 'wrong-issuer', - :verify_iss => true - } + JWT.decode token, data[:secret], true, iss: 'wrong-issuer', verify_iss: true end.to raise_error JWT::InvalidIssuerError end it 'valid iss should not raise JWT::InvalidIssuerError' do expect do - JWT.decode token, data[:secret], true, { - 'iss' => iss, - :verify_iss => true - } + JWT.decode token, data[:secret], true, iss: iss, verify_iss: true end.not_to raise_error end end context 'issued at claim' do let(:iat) { Time.now.to_i } - let(:new_payload) { payload.merge({ :iat => iat }) } + let(:new_payload) { payload.merge(iat: iat) } let(:token) { JWT.encode new_payload, data[:secret] } - let(:invalid_token) { JWT.encode new_payload.merge({ 'iat' => iat + 60 }), data[:secret] } + let(:invalid_token) { JWT.encode new_payload.merge('iat' => iat + 60), data[:secret] } let(:leeway) { 30 } it 'invalid iat should raise JWT::InvalidIatError' do expect do - JWT.decode invalid_token, data[:secret], true, { - :verify_iat => true - } + JWT.decode invalid_token, data[:secret], true, verify_iat: true end.to raise_error JWT::InvalidIatError end - it 'should ignore leeway' do + it 'should accept leeway' do expect do - JWT.decode invalid_token, data[:secret], true, { - :verify_iat => true, - :leeway => 70 - } - end.to raise_error JWT::InvalidIatError + JWT.decode invalid_token, data[:secret], true, verify_iat: true, leeway: 70 + end.to_not raise_error end it 'valid iat should not raise JWT::InvalidIatError' do expect do - JWT.decode token, data[:secret], true, { - :verify_iat => true - } + JWT.decode token, data[:secret], true, verify_iat: true end.to_not raise_error end end @@ -300,44 +287,32 @@ let(:array_aud) { %w(ruby-jwt-aud test-aud ruby-ruby-ruby) } let :simple_token do - new_payload = payload.merge({ 'aud' => simple_aud }) + new_payload = payload.merge('aud' => simple_aud) JWT.encode new_payload, data[:secret] end let :array_token do - new_payload = payload.merge({ 'aud' => array_aud }) + new_payload = payload.merge('aud' => array_aud) JWT.encode new_payload, data[:secret] end it 'invalid aud should raise JWT::InvalidAudError' do expect do - JWT.decode simple_token, data[:secret], true, { - 'aud' => 'wrong audience', - :verify_aud => true - } + JWT.decode simple_token, data[:secret], true, aud: 'wrong audience', verify_aud: true end.to raise_error JWT::InvalidAudError expect do - JWT.decode array_token, data[:secret], true, { - 'aud' => %w(wrong audience), - :verify_aud => true - } + JWT.decode array_token, data[:secret], true, aud: %w(wrong audience), verify_aud: true end.to raise_error JWT::InvalidAudError end it 'valid aud should not raise JWT::InvalidAudError' do expect do - JWT.decode simple_token, data[:secret], true, { - 'aud' => simple_aud, - :verify_aud => true - } + JWT.decode simple_token, data[:secret], true, 'aud' => simple_aud, :verify_aud => true end.to_not raise_error expect do - JWT.decode array_token, data[:secret], true, { - 'aud' => array_aud.first, - :verify_aud => true - } + JWT.decode array_token, data[:secret], true, 'aud' => array_aud.first, :verify_aud => true end.to_not raise_error end end @@ -346,39 +321,33 @@ let(:sub) { 'ruby jwt subject' } let :token do - new_payload = payload.merge({ 'sub' => sub }) + new_payload = payload.merge('sub' => sub) JWT.encode new_payload, data[:secret] end let :invalid_token do - new_payload = payload.merge({ 'sub' => 'we are not the druids you are looking for' }) + new_payload = payload.merge('sub' => 'we are not the druids you are looking for') JWT.encode new_payload, data[:secret] end it 'invalid sub should raise JWT::InvalidSubError' do expect do - JWT.decode invalid_token, data[:secret], true, { - 'sub' => sub, - :verify_sub => true - } + JWT.decode invalid_token, data[:secret], true, sub: sub, verify_sub: true end.to raise_error JWT::InvalidSubError end it 'valid sub should not raise JWT::InvalidSubError' do expect do - JWT.decode token, data[:secret], true, { - 'sub' => sub, - :verify_sub => true - } + JWT.decode token, data[:secret], true, 'sub' => sub, :verify_sub => true end.to_not raise_error end end context 'jwt id claim' do let :jti do - new_payload = payload.merge({ 'iat' => Time.now.to_i }) + new_payload = payload.merge('iat' => Time.now.to_i) key = data[:secret] - new_payload.merge({ 'jti' => Digest::MD5.hexdigest("#{key}:#{new_payload['iat']}") }) + new_payload.merge('jti' => Digest::MD5.hexdigest("#{key}:#{new_payload['iat']}")) end let(:token) { JWT.encode jti, data[:secret] } @@ -390,13 +359,13 @@ it 'invalid jti should raise JWT::InvalidJtiError' do expect do - JWT.decode invalid_token, data[:secret], true, { :verify_jti => true, 'jti' => jti['jti'] } + JWT.decode invalid_token, data[:secret], true, :verify_jti => true, 'jti' => jti['jti'] end.to raise_error JWT::InvalidJtiError end it 'valid jti should not raise JWT::InvalidJtiError' do expect do - JWT.decode token, data[:secret], true, { :verify_jti => true, 'jti' => jti['jti'] } + JWT.decode token, data[:secret], true, verify_jti: true, jti: jti['jti'] end.to_not raise_error end end From c63d321b39725d3ab5ab4316a00adcab6e55e4b7 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Sun, 20 Sep 2015 02:22:18 +0200 Subject: [PATCH 18/23] Drop ruby 1.9.2 support Missing OpenSSL functions --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b374a121..70c71e6d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ sudo: false cache: bundler language: ruby rvm: - - 1.9.2 - 1.9.3 - 2.0.0 - 2.1.0 From 0bb7da9fa5053619d8e415e35fef478711b94e51 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Sun, 20 Sep 2015 02:34:58 +0200 Subject: [PATCH 19/23] Add rubocop config --- .rubocop.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .rubocop.yml diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000..c4410459 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,2 @@ +Metrics/LineLength: + Enabled: false From 5ce6d7ef19c71cf5c24da1271adb6f5ac53c9882 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Sun, 20 Sep 2015 02:36:37 +0200 Subject: [PATCH 20/23] Fix rubocop issue --- lib/jwt/json.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/jwt/json.rb b/lib/jwt/json.rb index 48e30da6..a1cc8a54 100644 --- a/lib/jwt/json.rb +++ b/lib/jwt/json.rb @@ -8,7 +8,7 @@ module Json def decode_json(encoded) JSON.parse(encoded) rescue JSON::ParserError - raise JWT::DecodeError.new('Invalid segment encoding') + raise JWT::DecodeError, 'Invalid segment encoding' end def encode_json(raw) @@ -21,7 +21,7 @@ def encode_json(raw) def decode_json(encoded) MultiJson.decode(encoded) rescue MultiJson::LoadError - raise JWT::DecodeError.new('Invalid segment encoding') + raise JWT::DecodeError, 'Invalid segment encoding' end def encode_json(raw) From 528cb348dab541f7d528af51039a4af0ac20ff09 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Mon, 21 Sep 2015 22:53:30 +0200 Subject: [PATCH 21/23] Update README.md (cherry picked from commit ee7c24c4697ebcc050723ca1c0090a865c6788ec) --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 131e7204..ba21db7b 100644 --- a/README.md +++ b/README.md @@ -351,7 +351,8 @@ rake test * Zane Shannon [@zshannon](https://github.com/zshannon) * Brian Fletcher [@punkle](https://github.com/punkle) * Alex [@ZhangHanDong](https://github.com/ZhangHanDong) - * John Downey [jtdowney](https://github.com/jtdowney) + * John Downey [@jtdowney](https://github.com/jtdowney) + * Adam Greene [@skippy](https://github.com/skippy) * Tim Rudat [@excpt](https://github.com/excpt) - Maintainer ## License From 55bde4d810696ff84b3499ab1cf1b8c116113623 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Tue, 13 Oct 2015 22:27:39 +0200 Subject: [PATCH 22/23] Fix rubocop warning Remove whitespaces --- Rakefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Rakefile b/Rakefile index 5e5da513..09842b6a 100644 --- a/Rakefile +++ b/Rakefile @@ -4,13 +4,13 @@ require 'rake' require 'echoe' Echoe.new('jwt', '1.5.1') do |p| - p.description = 'JSON Web Token implementation in Ruby' - p.url = 'http://github.com/progrium/ruby-jwt' - p.author = 'Jeff Lindsay' - p.email = 'progrium@gmail.com' + p.description = 'JSON Web Token implementation in Ruby' + p.url = 'http://github.com/progrium/ruby-jwt' + p.author = 'Jeff Lindsay' + p.email = 'progrium@gmail.com' p.ignore_pattern = ['tmp/*'] p.development_dependencies = ['echoe >=4.6.3'] - p.licenses = 'MIT' + p.licenses = 'MIT' end task :test do From e86f15e5afeaf9fa6dcac2e67b50833b3d220e00 Mon Sep 17 00:00:00 2001 From: Tim Rudat Date: Mon, 26 Oct 2015 21:13:23 +0100 Subject: [PATCH 23/23] Update iss tests Add two iss claim tests from master branch. Fix a typo. --- spec/jwt_spec.rb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/spec/jwt_spec.rb b/spec/jwt_spec.rb index 14330436..9cfe0660 100644 --- a/spec/jwt_spec.rb +++ b/spec/jwt_spec.rb @@ -243,12 +243,26 @@ JWT.encode iss_payload, data[:secret] end + it 'if verify_iss is set to false (default option) should not raise JWT::InvalidIssuerError' do + expect do + JWT.decode token, data[:secret], true, iss: iss + end.not_to raise_error + end + it 'invalid iss should raise JWT::InvalidIssuerError' do expect do JWT.decode token, data[:secret], true, iss: 'wrong-issuer', verify_iss: true end.to raise_error JWT::InvalidIssuerError end + it 'with missing iss claim should raise JWT::InvalidIssuerError' do + missing_iss_claim_token = JWT.encode payload, data[:secret] + + expect do + JWT.decode missing_iss_claim_token, data[:secret], true, verify_iss: true, iss: iss + end.to raise_error(JWT::InvalidIssuerError, /received /) + end + it 'valid iss should not raise JWT::InvalidIssuerError' do expect do JWT.decode token, data[:secret], true, iss: iss, verify_iss: true @@ -256,7 +270,7 @@ end end - context 'issued at claim' do + context 'issued iat claim' do let(:iat) { Time.now.to_i } let(:new_payload) { payload.merge(iat: iat) } let(:token) { JWT.encode new_payload, data[:secret] }