Răsfoiți Sursa

Updated json checking.

- adapted to SJCL changed
- added entropy checking (from
https://github.com/vikstrous/ZeroBin/commit/f2ee2e8ba2f9c4cb1f16e81554c104109e202f24)

(cherry picked from commit 57e6274c64e2c99c754b63586af6b34c374fbc2b)

Conflicts:
	index.php
Sebastien SAUVAGE 13 ani în urmă
părinte
comite
7db76d8d71
2 a modificat fișierele cu 28 adăugiri și 11 ștergeri
  1. 15 5
      lib/sjcl.php
  2. 13 6
      tst/sjcl.php

+ 15 - 5
lib/sjcl.php

@@ -29,7 +29,7 @@ class sjcl
      */
     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
         $decoded = json_decode($encoded);
@@ -44,16 +44,26 @@ class sjcl
         // Make sure required fields are present and contain base64 data.
         foreach($accepted_keys as $k)
         {
-            if (!(
-                array_key_exists($k, $decoded) &&
-                $ct = base64_decode($decoded[$k], $strict=true)
-            )) return false;
+            if (!array_key_exists($k, $decoded)) 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.
         if (strlen($decoded['iv']) > 24) 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
         if (strlen($ct) > strlen(gzdeflate($ct))) return false;
 

+ 13 - 6
tst/sjcl.php

@@ -3,12 +3,19 @@ class sjclTest extends PHPUnit_Framework_TestCase
 {
     public function testSjclValidatorValidatesCorrectly()
     {
-        $this->assertTrue(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","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":"83Ax/OdUav3SanDW9dcQPg","salt":"$","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of salt');
+        $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":"$","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","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":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","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","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA","foo":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA="}'), 'invalid additional key');
+        $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","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","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
     }
 }