Skip to content

Commit 50afefb

Browse files
committed
Initial commit
1 parent 9029570 commit 50afefb

File tree

7 files changed

+381
-0
lines changed

7 files changed

+381
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
vendor/
2+
phpunit.phar

.travis.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
language: php
2+
php:
3+
- "5.6"
4+
script: phpunit tests/test.php
5+
install:
6+
- composer self-update
7+
- composer update --prefer-dist

README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,54 @@
11
# secure-functions
22
A collection of functions which can be used for security
3+
4+
## Instalation
5+
6+
#### Composer
7+
Install through composer and require the autoloader.
8+
9+
`composer require crecket/secure-functions`
10+
11+
#### Manual
12+
Download the files and require them in your project.
13+
14+
`require '/secure-functions/src/SecureFuncs.php';`
15+
16+
17+
18+
## Usage
19+
All functions are static public functions right now so you can simply call the functions like this:
20+
21+
`SecureFuncs\SecureFuncs::password_hash('input');`
22+
23+
24+
## Functions
25+
26+
### decrypt($input, $key)
27+
Returns the decryped output as a string using [defuse/php-encryption](https://github.com/defuse/php-encryption)'s library.
28+
29+
### encrypt($input, $key = false)
30+
Encrypt a string, if no key is given one will be generated for you (Recommended) using [defuse/php-encryption](https://github.com/defuse/php-encryption)'s library.
31+
32+
### password_hash($password)
33+
Hash the given password. This function allows for longer passwords and isn't affected by the null-byte issue.
34+
35+
### password_verify($password, $hash)
36+
Verify the given password hash
37+
38+
### randomHex($length)
39+
Returns a random hexadecimal number for the given length
40+
41+
### randomInt($min, $max)
42+
Returns the a secure random integer within the given range.
43+
44+
### randomSecureKey()
45+
Return a random key using [defuse/php-encryption](https://github.com/defuse/php-encryption)'s library.
46+
47+
### randomString($length)
48+
Returns a random string for the given length
49+
50+
### pseudoBytes($length)
51+
Returns random bytes for the given length
52+
53+
### strlen($str)
54+
Returns the length of the given string using mb_strlen when available

composer.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "crecket/secure-functions",
3+
"description": "Secure-functions makes it easier to secure functionality",
4+
"license": "WTFPL",
5+
"authors": [
6+
{
7+
"name": "Gregory Goijaerts",
8+
"email": "crecketgaming@gmail.com"
9+
}
10+
],
11+
"require": {
12+
"php": ">=5.6.0",
13+
"defuse/php-encryption": "^1.2"
14+
},
15+
"autoload": {
16+
"psr-4": {
17+
"SecureFuncs\\": "src/"
18+
}
19+
}
20+
}

composer.lock

Lines changed: 66 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/SecureFuncs.php

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
<?php
2+
namespace SecureFuncs;
3+
4+
class SecureFuncs
5+
{
6+
7+
public static $secret;
8+
9+
/**
10+
* @param $input
11+
* @param $key
12+
* @return string
13+
* @throws \CannotPerformOperationException
14+
* @throws \InvalidCiphertextException
15+
*/
16+
public static function decrypt($input, $key)
17+
{
18+
try {
19+
return \Crypto::decrypt($input, $key);
20+
} catch (Ex\InvalidCiphertextException $ex) {
21+
die('DANGER! DANGER! The ciphertext has been tampered with!');
22+
} catch (Ex\CryptoTestFailedException $ex) {
23+
die('Cannot safely perform decryption');
24+
} catch (Ex\CannotPerformOperationException $ex) {
25+
die('Cannot safely perform decryption');
26+
}
27+
}
28+
29+
/**
30+
* @param $input
31+
* @param bool $key
32+
* @return array
33+
* @throws CannotPerformOperationException
34+
* @throws \CannotPerformOperationException
35+
*/
36+
public static function encrypt($input, $key = false)
37+
{
38+
if ($key === false || GenericFuncs::strlen($key) !== Crypto::KEY_BYTE_SIZE) {
39+
$key = self::randomSecureKey();
40+
}
41+
42+
try {
43+
$ciphertext = \Crypto::encrypt($input, $key);
44+
} catch (Ex\CryptoTestFailedException $ex) {
45+
die('Cannot safely perform encryption');
46+
} catch (Ex\CannotPerformOperationException $ex) {
47+
die('Cannot safely perform encryption');
48+
}
49+
50+
return array('Key' => $key, 'Encrypted' => $ciphertext);
51+
}
52+
53+
/**
54+
* @param $password -> password to hash
55+
* @return bool|string
56+
*/
57+
public static function password_hash($password)
58+
{
59+
return password_hash(base64_encode(hash('sha256', $password, true)), PASSWORD_DEFAULT);
60+
}
61+
62+
/**
63+
* @param $password -> password to check
64+
* @param $hash -> hash to check
65+
* @return bool
66+
*/
67+
public static function password_verify($password, $hash)
68+
{
69+
return password_verify(base64_encode(hash('sha256', $password, true)), $hash);
70+
}
71+
72+
/**
73+
* @param int $length
74+
* @return string
75+
* @throws Exception
76+
*/
77+
public static function randomHex($length)
78+
{
79+
$bytes = \ceil($length / 2);
80+
$hex = \bin2hex(self::pseudoBytes($bytes));
81+
return $hex;
82+
}
83+
84+
/**
85+
* @param $min
86+
* @param $max
87+
* @return mixed
88+
* @throws \Exception
89+
*/
90+
public static function randomInt($min, $max)
91+
{
92+
if ($max <= $min) {
93+
throw new \Exception('Minimum equal or greater than maximum!');
94+
}
95+
if ($max < 0 || $min < 0) {
96+
throw new \Exception('Only positive integers supported for now!');
97+
}
98+
$difference = $max - $min;
99+
for ($power = 8; \pow(2, $power) < $difference; $power = $power * 2) ;
100+
$powerExp = $power / 8;
101+
102+
do {
103+
$randDiff = \hexdec(\bin2hex(self::pseudoBytes($powerExp)));
104+
} while ($randDiff > $difference);
105+
return $min + $randDiff;
106+
}
107+
108+
/**
109+
* @return string
110+
*/
111+
public static function randomSecureKey()
112+
{
113+
try {
114+
return \Crypto::createNewRandomKey();
115+
} catch (Ex\CryptoTestFailedException $ex) {
116+
die('Cannot safely create a key');
117+
} catch (Ex\CannotPerformOperationException $ex) {
118+
die('Cannot safely create a key');
119+
}
120+
}
121+
122+
/**
123+
* @param $length
124+
* @return string
125+
* @throws Exception
126+
*/
127+
public static function randomString($length)
128+
{
129+
130+
$charactersArr = \array_merge(\range('a', 'z'), \range('A', 'Z'), \range('0', '9'));
131+
132+
$charactersCount = \count($charactersArr);
133+
134+
$stringArr = array();
135+
136+
for ($character = 0; $character !== $length; $character++) {
137+
$stringArr[$character] = $charactersArr[self::randomInt(0, $charactersCount - 1)];
138+
}
139+
140+
return \implode($stringArr);
141+
}
142+
143+
/**
144+
* @param int $length
145+
* @return string
146+
* @throws \Exception
147+
*/
148+
public static function pseudoBytes($length = 1)
149+
{
150+
$bytes = openssl_random_pseudo_bytes($length, $strong);
151+
if ($strong === TRUE) {
152+
return $bytes;
153+
} else {
154+
throw new \Exception ('Insecure server! (OpenSSL Random byte generation insecure.)');
155+
}
156+
}
157+
158+
/**
159+
* @param $str
160+
* @return int
161+
* @throws CannotPerformOperationException
162+
*/
163+
public static function strlen($str)
164+
{
165+
if (function_exists('mb_strlen')) {
166+
$length = mb_strlen($str, '8bit');
167+
if ($length === FALSE) {
168+
throw new CannotPerformOperationException();
169+
}
170+
return $length;
171+
} else {
172+
return strlen($str);
173+
}
174+
}
175+
176+
}

tests/test.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
require __DIR__ . '/../vendor/autoload.php';
3+
4+
class test extends PHPUnit_Framework_TestCase
5+
{
6+
7+
public function testEncryptDecrypt()
8+
{
9+
10+
$message = "1234567890abcdefghijklmnopqrstuvwxyz";
11+
$encryptedData = SecureFuncs\SecureFuncs::encrypt($message);
12+
13+
$this->assertArrayHasKey('Key', $encryptedData);
14+
15+
$this->assertNotEmpty($encryptedData['Key']);
16+
17+
$this->assertArrayHasKey('Encrypted', $encryptedData);
18+
19+
$this->assertNotEmpty($encryptedData['Encrypted']);
20+
21+
$decryptedText = SecureFuncs\SecureFuncs::decrypt($encryptedData['Encrypted'], $encryptedData['Key']);
22+
23+
$this->assertEquals($message, $decryptedText);
24+
25+
}
26+
27+
public function testRandom()
28+
{
29+
30+
$this->assertNotEmpty(\SecureFuncs\SecureFuncs::pseudoBytes(32));
31+
32+
$this->assertStringMatchesFormat('%s', \SecureFuncs\SecureFuncs::randomHex(32));
33+
34+
$this->assertStringMatchesFormat('%s', \SecureFuncs\SecureFuncs::randomString(32));
35+
36+
$this->assertInternalType('int', \SecureFuncs\SecureFuncs::randomInt(32, 64));
37+
38+
}
39+
40+
public function testPassword()
41+
{
42+
43+
$password = "qwerty1234567";
44+
45+
$hash = \SecureFuncs\SecureFuncs::password_hash($password);
46+
47+
$this->assertInternalType('string', $hash);
48+
49+
$this->assertTrue(\SecureFuncs\SecureFuncs::password_verify($password, $hash));
50+
51+
}
52+
53+
public function testOther()
54+
{
55+
$this->assertEquals(9, \SecureFuncs\SecureFuncs::strlen('123456789'));
56+
}
57+
58+
}

0 commit comments

Comments
 (0)