aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs/Lib/Crypto.php
diff options
context:
space:
mode:
Diffstat (limited to 'Zotlabs/Lib/Crypto.php')
-rw-r--r--Zotlabs/Lib/Crypto.php206
1 files changed, 206 insertions, 0 deletions
diff --git a/Zotlabs/Lib/Crypto.php b/Zotlabs/Lib/Crypto.php
new file mode 100644
index 000000000..f1794ae64
--- /dev/null
+++ b/Zotlabs/Lib/Crypto.php
@@ -0,0 +1,206 @@
+<?php
+
+namespace Zotlabs\Lib;
+
+use Exception;
+
+class Crypto {
+
+ public static $openssl_algorithms = [
+
+ // zot6 nickname, opensslname, keylength, ivlength
+
+ ['aes256ctr', 'aes-256-ctr', 32, 16],
+ ['camellia256cfb', 'camellia-256-cfb', 32, 16],
+ ['cast5cfb', 'cast5-cfb', 16, 8],
+ ['aes256cbc', 'aes-256-cbc', 32, 16] // remove after legacy zot has been sunset
+
+ ];
+
+ public static function methods() {
+ $ret = [];
+
+ foreach (self::$openssl_algorithms as $ossl) {
+ $ret[] = $ossl[0] . '.oaep';
+ }
+
+ call_hooks('crypto_methods', $ret);
+ return $ret;
+ }
+
+ public static function signing_methods() {
+
+ $ret = ['sha256'];
+ call_hooks('signing_methods', $ret);
+ return $ret;
+
+ }
+
+ public static function new_keypair($bits) {
+
+ $openssl_options = [
+ 'digest_alg' => 'sha1',
+ 'private_key_bits' => $bits,
+ 'encrypt_key' => false
+ ];
+
+ $conf = get_config('system', 'openssl_conf_file');
+
+ if ($conf) {
+ $openssl_options['config'] = $conf;
+ }
+
+ $result = openssl_pkey_new($openssl_options);
+
+ if (empty($result)) {
+ return false;
+ }
+
+ // Get private key
+
+ $response = ['prvkey' => '', 'pubkey' => ''];
+
+ openssl_pkey_export($result, $response['prvkey']);
+
+ // Get public key
+ $pkey = openssl_pkey_get_details($result);
+ $response['pubkey'] = $pkey["key"];
+
+ return $response;
+
+ }
+
+ public static function sign($data, $key, $alg = 'sha256') {
+
+ if (!$key) {
+ return false;
+ }
+
+ $sig = '';
+ openssl_sign($data, $sig, $key, $alg);
+ return $sig;
+ }
+
+ public static function verify($data, $sig, $key, $alg = 'sha256') {
+
+ if (!$key) {
+ return false;
+ }
+
+ try {
+ $verify = openssl_verify($data, $sig, $key, $alg);
+ } catch (Exception $e) {
+ $verify = (-1);
+ }
+
+ if ($verify === (-1)) {
+ while ($msg = openssl_error_string()) {
+ logger('openssl_verify: ' . $msg, LOGGER_NORMAL, LOG_ERR);
+ }
+ btlogger('openssl_verify: key: ' . $key, LOGGER_DEBUG, LOG_ERR);
+ }
+
+ return (($verify > 0) ? true : false);
+ }
+
+ public static function encapsulate($data, $pubkey, $alg) {
+
+ if (!($alg && $pubkey)) {
+ return $data;
+ }
+
+ $alg_base = $alg;
+ $padding = OPENSSL_PKCS1_PADDING;
+
+ $exts = explode('.', $alg);
+ if (count($exts) > 1) {
+ switch ($exts[1]) {
+ case 'oaep':
+ $padding = OPENSSL_PKCS1_OAEP_PADDING;
+ break;
+ default:
+ break;
+ }
+ $alg_base = $exts[0];
+ }
+
+ $method = null;
+
+ foreach (self::$openssl_algorithms as $ossl) {
+ if ($ossl[0] === $alg_base) {
+ $method = $ossl;
+ break;
+ }
+ }
+
+ if ($method) {
+ $result = ['encrypted' => true];
+
+ $key = openssl_random_pseudo_bytes(256);
+ $iv = openssl_random_pseudo_bytes(256);
+
+ $key1 = substr($key, 0, $method[2]);
+ $iv1 = substr($iv, 0, $method[3]);
+
+ $result['data'] = base64url_encode(openssl_encrypt($data, $method[1], $key1, OPENSSL_RAW_DATA, $iv1), true);
+
+ openssl_public_encrypt($key, $k, $pubkey, $padding);
+ openssl_public_encrypt($iv, $i, $pubkey, $padding);
+
+ $result['alg'] = $alg;
+ $result['key'] = base64url_encode($k, true);
+ $result['iv'] = base64url_encode($i, true);
+ return $result;
+
+ }
+ else {
+ $x = ['data' => $data, 'pubkey' => $pubkey, 'alg' => $alg, 'result' => $data];
+ call_hooks('crypto_encapsulate', $x);
+ return $x['result'];
+ }
+ }
+
+ public static function unencapsulate($data, $prvkey) {
+
+ if (!(is_array($data) && array_key_exists('encrypted', $data) && array_key_exists('alg', $data) && $data['alg'])) {
+ logger('not encrypted');
+
+ return $data;
+ }
+
+ $alg_base = $data['alg'];
+ $padding = OPENSSL_PKCS1_PADDING;
+
+ $exts = explode('.', $data['alg']);
+ if (count($exts) > 1) {
+ switch ($exts[1]) {
+ case 'oaep':
+ $padding = OPENSSL_PKCS1_OAEP_PADDING;
+ break;
+ default:
+ break;
+ }
+ $alg_base = $exts[0];
+ }
+
+ $method = null;
+
+ foreach (self::$openssl_algorithms as $ossl) {
+ if ($ossl[0] === $alg_base) {
+ $method = $ossl;
+ break;
+ }
+ }
+
+ if ($method) {
+ openssl_private_decrypt(base64url_decode($data['key']), $k, $prvkey, $padding);
+ openssl_private_decrypt(base64url_decode($data['iv']), $i, $prvkey, $padding);
+ return openssl_decrypt(base64url_decode($data['data']), $method[1], substr($k, 0, $method[2]), OPENSSL_RAW_DATA, substr($i, 0, $method[3]));
+ }
+ else {
+ $x = ['data' => $data, 'prvkey' => $prvkey, 'alg' => $data['alg'], 'result' => $data];
+ call_hooks('crypto_unencapsulate', $x);
+ return $x['result'];
+ }
+ }
+}