implement version 2 format validation, changing ID checksum algorithm, resolves #49

This commit is contained in:
El RIDO
2019-05-03 23:03:57 +02:00
parent ed676acac3
commit 3338bd792e
12 changed files with 233 additions and 185 deletions

View File

@@ -28,7 +28,7 @@ class Helper
*
* @var string
*/
private static $pasteid = '5e9bc25c89fb3bf9';
private static $pasteid = '5b65a01b43987bc2';
/**
* example paste version 1

71
tst/FormatV2Test.php Normal file
View File

@@ -0,0 +1,71 @@
<?php
use PrivateBin\FormatV2;
class FormatV2Test extends PHPUnit_Framework_TestCase
{
public function testFormatV2ValidatorValidatesCorrectly()
{
$this->assertTrue(FormatV2::isValid(Helper::getPaste()), 'valid format');
$this->assertTrue(FormatV2::isValid(Helper::getComment(), true), 'valid format');
$paste = Helper::getPaste();
$paste['adata'][0][0] = '$';
$this->assertFalse(FormatV2::isValid($paste), 'invalid base64 encoding of iv');
$paste = Helper::getPaste();
$paste['adata'][0][1] = '$';
$this->assertFalse(FormatV2::isValid($paste), 'invalid base64 encoding of salt');
$paste = Helper::getPaste();
$paste['ct'] = '$';
$this->assertFalse(FormatV2::isValid($paste), 'invalid base64 encoding of ct');
$paste = Helper::getPaste();
$paste['ct'] = 'bm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhCg==';
$this->assertFalse(FormatV2::isValid($paste), 'low ct entropy');
$paste = Helper::getPaste();
$paste['adata'][0][0] = 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=';
$this->assertFalse(FormatV2::isValid($paste), 'iv too long');
$paste = Helper::getPaste();
$paste['adata'][0][1] = 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=';
$this->assertFalse(FormatV2::isValid($paste), 'salt too long');
$paste = Helper::getPaste();
$paste['foo'] = 'bar';
$this->assertFalse(FormatV2::isValid($paste), 'invalid additional key');
unset($paste['meta']);
$this->assertFalse(FormatV2::isValid($paste), 'invalid missing key');
$paste = Helper::getPaste();
$paste['v'] = 0.9;
$this->assertFalse(FormatV2::isValid($paste), 'unsupported version');
$paste = Helper::getPaste();
$paste['adata'][0][2] = 1000;
$this->assertFalse(FormatV2::isValid($paste), 'not enough iterations');
$paste = Helper::getPaste();
$paste['adata'][0][3] = 127;
$this->assertFalse(FormatV2::isValid($paste), 'invalid key size');
$paste = Helper::getPaste();
$paste['adata'][0][4] = 63;
$this->assertFalse(FormatV2::isValid($paste), 'invalid tag length');
$paste = Helper::getPaste();
$paste['adata'][0][5] = '!#@';
$this->assertFalse(FormatV2::isValid($paste), 'invalid algorithm');
$paste = Helper::getPaste();
$paste['adata'][0][6] = '!#@';
$this->assertFalse(FormatV2::isValid($paste), 'invalid mode');
$paste = Helper::getPaste();
$paste['adata'][0][7] = '!#@';
$this->assertFalse(FormatV2::isValid($paste), 'invalid compression');
}
}

View File

@@ -60,15 +60,15 @@ class ModelTest extends PHPUnit_Framework_TestCase
$this->assertFalse($paste->exists(), 'paste does not yet exist');
$paste = $this->_model->getPaste();
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->setOpendiscussion();
$paste->setFormatter($pasteData['meta']['formatter']);
$paste->setFormatter($pasteData['adata'][1]);
$paste->store();
$paste = $this->_model->getPaste(Helper::getPasteId());
$this->assertTrue($paste->exists(), 'paste exists after storing it');
$paste = $paste->get();
$this->assertEquals($pasteData['data'], $paste->data);
$this->assertEquals($pasteData, $paste->data);
foreach (array('opendiscussion', 'formatter') as $key) {
$this->assertEquals($pasteData['meta'][$key], $paste->meta->$key);
}
@@ -80,7 +80,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
$this->assertFalse($comment->exists(), 'comment does not yet exist');
$comment = $paste->getComment(Helper::getPasteId());
$comment->setData($commentData['data']);
$comment->setData($commentData);
$comment->setNickname($commentData['meta']['nickname']);
$comment->getParentId();
$comment->store();
@@ -88,7 +88,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
$comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId());
$this->assertTrue($comment->exists(), 'comment exists after storing it');
$comment = $comment->get();
$this->assertEquals($commentData['data'], $comment->data);
$this->assertEquals($commentData, $comment->data);
$this->assertEquals($commentData['meta']['nickname'], $comment->meta->nickname);
// deleting pastes
@@ -108,15 +108,15 @@ class ModelTest extends PHPUnit_Framework_TestCase
$this->_model->getPaste(Helper::getPasteId())->delete();
$paste = $this->_model->getPaste();
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->setOpendiscussion();
$paste->setFormatter($pasteData['meta']['formatter']);
$paste->setFormatter($pasteData['adata'][1]);
$paste->store();
$paste = $this->_model->getPaste();
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->setOpendiscussion();
$paste->setFormatter($pasteData['meta']['formatter']);
$paste->setFormatter($pasteData['adata'][1]);
$paste->store();
}
@@ -131,18 +131,18 @@ class ModelTest extends PHPUnit_Framework_TestCase
$this->_model->getPaste(Helper::getPasteId())->delete();
$paste = $this->_model->getPaste();
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->setOpendiscussion();
$paste->setFormatter($pasteData['meta']['formatter']);
$paste->setFormatter($pasteData['adata'][1]);
$paste->store();
$comment = $paste->getComment(Helper::getPasteId());
$comment->setData($commentData['data']);
$comment->setData($commentData);
$comment->setNickname($commentData['meta']['nickname']);
$comment->store();
$comment = $paste->getComment(Helper::getPasteId());
$comment->setData($commentData['data']);
$comment->setData($commentData);
$comment->setNickname($commentData['meta']['nickname']);
$comment->store();
}
@@ -154,7 +154,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
$this->_model->getPaste(Helper::getPasteId())->delete();
$paste = $this->_model->getPaste();
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->setBurnafterreading();
$paste->setOpendiscussion();
// not setting a formatter, should use default one
@@ -167,13 +167,13 @@ class ModelTest extends PHPUnit_Framework_TestCase
$this->_model->getPaste(Helper::getPasteId())->delete();
$paste = $this->_model->getPaste();
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->setBurnafterreading('0');
$paste->setOpendiscussion();
$paste->store();
$comment = $paste->getComment(Helper::getPasteId());
$comment->setData($commentData['data']);
$comment->setData($commentData);
$comment->setNickname($commentData['meta']['nickname']);
$comment->store();
@@ -208,7 +208,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
public function testInvalidData()
{
$paste = $this->_model->getPaste();
$paste->setData('');
$paste->setData(array());
}
/**
@@ -229,7 +229,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
{
$pasteData = Helper::getPaste();
$paste = $this->_model->getPaste(Helper::getPasteId());
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->store();
$comment = $paste->getComment(Helper::getPasteId());
@@ -245,7 +245,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
{
$pasteData = Helper::getPaste();
$paste = $this->_model->getPaste(Helper::getPasteId());
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->store();
$comment = $paste->getComment(Helper::getPasteId());
@@ -260,7 +260,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
$this->assertFalse($paste->exists(), 'paste does not yet exist');
$paste = $this->_model->getPaste();
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->setExpiration('5min'); // = 300 seconds
$paste->store();
@@ -278,7 +278,7 @@ class ModelTest extends PHPUnit_Framework_TestCase
$this->_model->getPaste(Helper::getPasteId())->delete();
$paste = $this->_model->getPaste();
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->store();
$paste->getComment(Helper::getPasteId())->delete();
}
@@ -336,15 +336,15 @@ class ModelTest extends PHPUnit_Framework_TestCase
$this->assertFalse($paste->exists(), 'paste does not yet exist');
$paste = $model->getPaste();
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->setOpendiscussion();
$paste->setFormatter($pasteData['meta']['formatter']);
$paste->setFormatter($pasteData['adata'][1]);
$paste->store();
$paste = $model->getPaste(Helper::getPasteId());
$this->assertTrue($paste->exists(), 'paste exists after storing it');
$paste = $paste->get();
$this->assertEquals($pasteData['data'], $paste->data);
$this->assertEquals($pasteData, $paste->data);
foreach (array('opendiscussion', 'formatter') as $key) {
$this->assertEquals($pasteData['meta'][$key], $paste->meta->$key);
}
@@ -356,14 +356,14 @@ class ModelTest extends PHPUnit_Framework_TestCase
$this->assertFalse($comment->exists(), 'comment does not yet exist');
$comment = $paste->getComment(Helper::getPasteId());
$comment->setData($commentData['data']);
$comment->setData($commentData);
$comment->setNickname($commentData['meta']['nickname']);
$comment->store();
$comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId());
$this->assertTrue($comment->exists(), 'comment exists after storing it');
$comment = $comment->get();
$this->assertEquals($commentData['data'], $comment->data);
$this->assertEquals($commentData, $comment->data);
$this->assertEquals($commentData['meta']['nickname'], $comment->meta->nickname);
$this->assertFalse(property_exists($comment->meta, 'vizhash'), 'vizhash was not generated');
}
@@ -389,13 +389,13 @@ class ModelTest extends PHPUnit_Framework_TestCase
$model->getPaste(Helper::getPasteId())->delete();
$paste = $model->getPaste();
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->setOpendiscussion();
$paste->setFormatter($pasteData['meta']['formatter']);
$paste->setFormatter($pasteData['adata'][1]);
$paste->store();
$comment = $paste->getComment(Helper::getPasteId());
$comment->setData($commentData['data']);
$comment->setData($commentData);
$comment->setNickname($commentData['meta']['nickname']);
$comment->store();
@@ -426,13 +426,13 @@ class ModelTest extends PHPUnit_Framework_TestCase
$model->getPaste(Helper::getPasteId())->delete();
$paste = $model->getPaste();
$paste->setData($pasteData['data']);
$paste->setData($pasteData);
$paste->setOpendiscussion();
$paste->setFormatter($pasteData['meta']['formatter']);
$paste->setFormatter($pasteData['adata'][1]);
$paste->store();
$comment = $paste->getComment(Helper::getPasteId());
$comment->setData($commentData['data']);
$comment->setData($commentData);
$comment->setNickname($commentData['meta']['nickname']);
$comment->store();

View File

@@ -1,33 +0,0 @@
<?php
use PrivateBin\Persistence\ServerSalt;
use PrivateBin\Sjcl;
class SjclTest extends PHPUnit_Framework_TestCase
{
public function testSjclValidatorValidatesCorrectly()
{
ServerSalt::setPath(sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data');
$paste = Helper::getPasteWithAttachment();
$this->assertTrue(Sjcl::isValid($paste['data']), 'valid sjcl');
$this->assertTrue(Sjcl::isValid($paste['attachment']), 'valid sjcl');
$this->assertTrue(Sjcl::isValid($paste['attachmentname']), 'valid sjcl');
$this->assertTrue(Sjcl::isValid(Helper::getComment()['data']), '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":"$","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","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"$"}'), 'invalid base64 encoding of ct');
$this->assertFalse(Sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"Gx1vA2/gQ3U","ct":"bm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhbm9kYXRhCg=="}'), 'low ct entropy');
$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
}
}