|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Blocktrail\SDK\V3Crypt; |
|
4
|
|
|
|
|
5
|
|
|
use AESGCM\AESGCM; |
|
6
|
|
|
use BitWasp\Buffertools\Buffer; |
|
7
|
|
|
use BitWasp\Buffertools\BufferInterface; |
|
8
|
|
|
use BitWasp\Buffertools\Buffertools; |
|
9
|
|
|
use BitWasp\Buffertools\Parser; |
|
10
|
|
|
|
|
11
|
|
|
class Encryption |
|
12
|
|
|
{ |
|
13
|
|
|
const DEFAULT_SALTLEN = 10; |
|
14
|
|
|
const TAGLEN_BITS = 128; |
|
15
|
|
|
const IVLEN_BYTES = 16; |
|
16
|
|
|
|
|
17
|
|
|
/** |
|
18
|
|
|
* @param BufferInterface $pt |
|
19
|
|
|
* @param BufferInterface $pw |
|
20
|
|
|
* @return BufferInterface |
|
21
|
|
|
*/ |
|
22
|
|
|
public static function encrypt(BufferInterface $pt, BufferInterface $pw) { |
|
23
|
|
|
$salt = new Buffer(random_bytes(self::DEFAULT_SALTLEN)); |
|
24
|
|
|
$iv = new Buffer(random_bytes(self::IVLEN_BYTES)); |
|
25
|
|
|
$iterations = KeyDerivation::DEFAULT_ITERATIONS; |
|
26
|
|
|
return self::encryptWithSaltAndIV($pt, $pw, $salt, $iv, $iterations); |
|
27
|
|
|
} |
|
28
|
|
|
|
|
29
|
|
|
/** |
|
30
|
|
|
* @param BufferInterface $ct |
|
31
|
|
|
* @param BufferInterface $pw |
|
32
|
|
|
* @return BufferInterface |
|
33
|
|
|
*/ |
|
34
|
|
|
public static function decrypt(BufferInterface $ct, BufferInterface $pw) { |
|
35
|
|
|
$parser = new Parser($ct); |
|
36
|
|
|
$sLB = $parser->readBytes(1); |
|
37
|
|
|
$salt = $parser->readBytes($sLB->getInt()); |
|
38
|
|
|
$itB = $parser->readBytes(4); |
|
39
|
|
|
$header = new Buffer($sLB->getBinary() . $salt->getBinary() . $itB->getBinary()); |
|
40
|
|
|
|
|
41
|
|
|
$iv = $parser->readBytes(16); |
|
42
|
|
|
$act = $parser->readBytes($ct->getSize() - $parser->getPosition()); |
|
43
|
|
|
$tag = $act->slice(-16); |
|
44
|
|
|
$ct = $act->slice(0, -16); |
|
45
|
|
|
|
|
46
|
|
|
return new Buffer( |
|
47
|
|
|
AESGCM::decrypt( |
|
48
|
|
|
KeyDerivation::compute($pw, $salt, unpack('V', $itB->getBinary())[1])->getBinary(), |
|
49
|
|
|
$iv->getBinary(), |
|
50
|
|
|
$ct->getBinary(), |
|
51
|
|
|
$header->getBinary(), |
|
52
|
|
|
$tag->getBinary() |
|
53
|
|
|
) |
|
54
|
|
|
); |
|
55
|
|
|
} |
|
56
|
|
|
|
|
57
|
|
|
/** |
|
58
|
|
|
* @param BufferInterface $pt |
|
59
|
|
|
* @param BufferInterface $pw |
|
60
|
|
|
* @param BufferInterface $salt |
|
61
|
|
|
* @param BufferInterface $iv |
|
62
|
|
|
* @param int $iterations |
|
63
|
|
|
* @return BufferInterface |
|
64
|
|
|
*/ |
|
65
|
|
|
public static function encryptWithSaltAndIV(BufferInterface $pt, BufferInterface $pw, BufferInterface $salt, BufferInterface $iv, $iterations) { |
|
66
|
|
|
if ($iv->getSize() !== 16) { |
|
67
|
|
|
throw new \RuntimeException('IV must be exactly 16 bytes'); |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
$header = new Buffer(pack('c', $salt->getSize()) . $salt->getBinary() . pack('V', $iterations)); |
|
71
|
|
|
|
|
72
|
|
|
list ($ct, $tag) = AESGCM::encrypt( |
|
73
|
|
|
KeyDerivation::compute($pw, $salt, $iterations)->getBinary(), |
|
74
|
|
|
$iv->getBinary(), |
|
75
|
|
|
$pt->getBinary(), |
|
76
|
|
|
$header->getBinary() |
|
77
|
|
|
); |
|
78
|
|
|
|
|
79
|
|
|
return Buffertools::concat($header, new Buffer($iv->getBinary() . $ct . $tag)); |
|
80
|
|
|
} |
|
81
|
|
|
} |
|
82
|
|
|
|