Updated json checking.
- adapted to SJCL changed
- added entropy checking (from
f2ee2e8ba2
)
(cherry picked from commit 57e6274c64e2c99c754b63586af6b34c374fbc2b)
Conflicts:
index.php
This commit is contained in:
parent
315c45ed0c
commit
7db76d8d71
20
lib/sjcl.php
20
lib/sjcl.php
|
@ -29,7 +29,7 @@ class sjcl
|
||||||
*/
|
*/
|
||||||
public static function isValid($encoded)
|
public static function isValid($encoded)
|
||||||
{
|
{
|
||||||
$accepted_keys = array('iv','salt','ct');
|
$accepted_keys = array('iv','v','iter','ks','ts','mode','adata','cipher','salt','ct');
|
||||||
|
|
||||||
// Make sure content is valid json
|
// Make sure content is valid json
|
||||||
$decoded = json_decode($encoded);
|
$decoded = json_decode($encoded);
|
||||||
|
@ -44,16 +44,26 @@ class sjcl
|
||||||
// Make sure required fields are present and contain base64 data.
|
// Make sure required fields are present and contain base64 data.
|
||||||
foreach($accepted_keys as $k)
|
foreach($accepted_keys as $k)
|
||||||
{
|
{
|
||||||
if (!(
|
if (!array_key_exists($k, $decoded)) return false;
|
||||||
array_key_exists($k, $decoded) &&
|
|
||||||
$ct = base64_decode($decoded[$k], $strict=true)
|
|
||||||
)) return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure some fields are base64 data.
|
||||||
|
if (!base64_decode($decoded['iv'], true)) return false;
|
||||||
|
if (!base64_decode($decoded['salt'], true)) return false;
|
||||||
|
if (!($ct = base64_decode($decoded['ct'], true))) return false;
|
||||||
|
|
||||||
// Make sure some fields have a reasonable size.
|
// Make sure some fields have a reasonable size.
|
||||||
if (strlen($decoded['iv']) > 24) return false;
|
if (strlen($decoded['iv']) > 24) return false;
|
||||||
if (strlen($decoded['salt']) > 14) return false;
|
if (strlen($decoded['salt']) > 14) return false;
|
||||||
|
|
||||||
|
// Make sure some fields contain no unsupported values.
|
||||||
|
if (!(is_int($decoded['v']) || is_float($decoded['v'])) || (float) $decoded['v'] < 1) return false;
|
||||||
|
if (!is_int($decoded['iter']) || $decoded['iter'] <= 100) return false;
|
||||||
|
if (!in_array($decoded['ks'], array(128, 192, 256), true)) return false;
|
||||||
|
if (!in_array($decoded['ts'], array(64, 96, 128), true)) return false;
|
||||||
|
if (!in_array($decoded['mode'], array('ccm', 'ocb2', 'gcm'), true)) return false;
|
||||||
|
if ($decoded['cipher'] !== 'aes') return false;
|
||||||
|
|
||||||
// Reject data if entropy is too low
|
// Reject data if entropy is too low
|
||||||
if (strlen($ct) > strlen(gzdeflate($ct))) return false;
|
if (strlen($ct) > strlen(gzdeflate($ct))) return false;
|
||||||
|
|
||||||
|
|
19
tst/sjcl.php
19
tst/sjcl.php
|
@ -3,12 +3,19 @@ class sjclTest extends PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
public function testSjclValidatorValidatesCorrectly()
|
public function testSjclValidatorValidatesCorrectly()
|
||||||
{
|
{
|
||||||
$this->assertTrue(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'valid sjcl');
|
$this->assertTrue(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'valid sjcl');
|
||||||
$this->assertFalse(sjcl::isValid('{"iv":"$","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of iv');
|
$this->assertFalse(sjcl::isValid('{"iv":"$","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of iv');
|
||||||
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","salt":"$","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of salt');
|
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"$","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of salt');
|
||||||
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","salt":"Gx1vA2/gQ3U","ct":"$"}'), 'invalid base64 encoding of ct');
|
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","salt":"Gx1vA2/gQ3U","ct":"$"}'), 'invalid base64 encoding of ct');
|
||||||
$this->assertFalse(sjcl::isValid('{"iv":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'iv to long');
|
$this->assertFalse(sjcl::isValid('{"iv":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'iv to long');
|
||||||
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","salt":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'salt to long');
|
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'salt to long');
|
||||||
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA","foo":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA="}'), 'invalid additional key');
|
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA","foo":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA="}'), 'invalid additional key');
|
||||||
|
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":0.9,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'unsupported version');
|
||||||
|
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":100,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'not enough iterations');
|
||||||
|
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":127,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid key size');
|
||||||
|
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":63,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid tag length');
|
||||||
|
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"!#@","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid mode');
|
||||||
|
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"!#@","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid cipher');
|
||||||
|
// @note adata is not validated, except as part of the total message length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue