+++ /dev/null
-<?php
-//-----------------------------------------------------------------------------
-// ASNValue class by A.Oliinyk
-// contact@pumka.net
-//-----------------------------------------------------------------------------
-class ASNValue
-{
- const TAG_INTEGER = 0x02;
- const TAG_BITSTRING = 0x03;
- const TAG_SEQUENCE = 0x30;
-
- public $Tag;
- public $Value;
-
- function __construct($Tag=0x00, $Value='')
- {
- $this->Tag = $Tag;
- $this->Value = $Value;
- }
-
- function Encode()
- {
- //Write type
- $result = chr($this->Tag);
-
- //Write size
- $size = strlen($this->Value);
- if ($size < 127) {
- //Write size as is
- $result .= chr($size);
- }
- else {
- //Prepare length sequence
- $sizeBuf = self::IntToBin($size);
-
- //Write length sequence
- $firstByte = 0x80 + strlen($sizeBuf);
- $result .= chr($firstByte) . $sizeBuf;
- }
-
- //Write value
- $result .= $this->Value;
-
- return $result;
- }
-
- function Decode(&$Buffer)
- {
- //Read type
- $this->Tag = self::ReadByte($Buffer);
-
- //Read first byte
- $firstByte = self::ReadByte($Buffer);
-
- if ($firstByte < 127) {
- $size = $firstByte;
- }
- else if ($firstByte > 127) {
- $sizeLen = $firstByte - 0x80;
- //Read length sequence
- $size = self::BinToInt(self::ReadBytes($Buffer, $sizeLen));
- }
- else {
- throw new Exception("Invalid ASN length value");
- }
-
- $this->Value = self::ReadBytes($Buffer, $size);
- }
-
- protected static function ReadBytes(&$Buffer, $Length)
- {
- $result = substr($Buffer, 0, $Length);
- $Buffer = substr($Buffer, $Length);
-
- return $result;
- }
-
- protected static function ReadByte(&$Buffer)
- {
- return ord(self::ReadBytes($Buffer, 1));
- }
-
- protected static function BinToInt($Bin)
- {
- $len = strlen($Bin);
- $result = 0;
- for ($i=0; $i<$len; $i++) {
- $curByte = self::ReadByte($Bin);
- $result += $curByte << (($len-$i-1)*8);
- }
-
- return $result;
- }
-
- protected static function IntToBin($Int)
- {
- $result = '';
- do {
- $curByte = $Int % 256;
- $result .= chr($curByte);
-
- $Int = ($Int - $curByte) / 256;
- } while ($Int > 0);
-
- $result = strrev($result);
-
- return $result;
- }
-
- function SetIntBuffer($Value)
- {
- if (strlen($Value) > 1) {
- $firstByte = ord($Value[0]);
- if ($firstByte & 0x80) { //first bit set
- $Value = chr(0x00) . $Value;
- }
- }
-
- $this->Value = $Value;
- }
-
- function GetIntBuffer()
- {
- $result = $this->Value;
- if (ord($result[0]) == 0x00) {
- $result = substr($result, 1);
- }
-
- return $result;
- }
-
- function SetInt($Value)
- {
- $Value = self::IntToBin($Value);
-
- $this->SetIntBuffer($Value);
- }
-
- function GetInt()
- {
- $result = $this->GetIntBuffer();
- $result = self::BinToInt($result);
-
- return $result;
- }
-
- function SetSequence($Values)
- {
- $result = '';
- foreach ($Values as $item) {
- $result .= $item->Encode();
- }
-
- $this->Value = $result;
- }
-
- function GetSequence()
- {
- $result = array();
- $seq = $this->Value;
- while (strlen($seq)) {
- $val = new ASNValue();
- $val->Decode($seq);
- $result[] = $val;
- }
-
- return $result;
- }
-}
namespace Friendica\Util;
-use ASNValue;
use Friendica\Core\Hook;
use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\DI;
use phpseclib\Crypt\RSA;
+use phpseclib\Math\BigInteger;
/**
* Crypto class
}
/**
- * @param string $Der der formatted string
- * @param bool $Private key type optional, default false
- * @return string
- */
- private static function DerToPem($Der, $Private = false)
- {
- //Encode:
- $Der = base64_encode($Der);
- //Split lines:
- $lines = str_split($Der, 65);
- $body = implode("\n", $lines);
- //Get title:
- $title = $Private ? 'RSA PRIVATE KEY' : 'PUBLIC KEY';
- //Add wrapping:
- $result = "-----BEGIN {$title}-----\n";
- $result .= $body . "\n";
- $result .= "-----END {$title}-----\n";
-
- return $result;
- }
-
- /**
- * @param string $Modulus modulo
- * @param string $PublicExponent exponent
- * @return string
- */
- private static function pkcs8Encode($Modulus, $PublicExponent)
- {
- //Encode key sequence
- $modulus = new ASNValue(ASNValue::TAG_INTEGER);
- $modulus->SetIntBuffer($Modulus);
- $publicExponent = new ASNValue(ASNValue::TAG_INTEGER);
- $publicExponent->SetIntBuffer($PublicExponent);
- $keySequenceItems = [$modulus, $publicExponent];
- $keySequence = new ASNValue(ASNValue::TAG_SEQUENCE);
- $keySequence->SetSequence($keySequenceItems);
- //Encode bit string
- $bitStringValue = $keySequence->Encode();
- $bitStringValue = chr(0x00) . $bitStringValue; //Add unused bits byte
- $bitString = new ASNValue(ASNValue::TAG_BITSTRING);
- $bitString->Value = $bitStringValue;
- //Encode body
- $bodyValue = "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00" . $bitString->Encode();
- $body = new ASNValue(ASNValue::TAG_SEQUENCE);
- $body->Value = $bodyValue;
- //Get DER encoded public key:
- $PublicDER = $body->Encode();
- return $PublicDER;
- }
-
/**
* @param string $m modulo
* @param string $e exponent
*/
public static function meToPem($m, $e)
{
- $der = self::pkcs8Encode($m, $e);
- $key = self::DerToPem($der, false);
- return $key;
+ $rsa = new RSA();
+ $rsa->loadKey([
+ 'e' => new BigInteger($e, 256),
+ 'n' => new BigInteger($m, 256)
+ ]);
+ return $rsa->getPublicKey();
}
/**
*
* @return void
*/
- public static function pemToMe(string $key, string &$modulus, string &$exponent)
+ public static function pemToMe(string $key, &$modulus, &$exponent)
{
$publicKey = new RSA();
$publicKey->loadKey($key);
}
- public function datePem()
+ public function dataPEM()
{
return [
'diaspora' => [
}
/**
- * @dataProvider datePem
+ * @dataProvider dataPEM
*/
public function testPemToMe(string $key)
{
$this->assertEquals($expectedRSA->getPublicKey(), $key);
}
+
+ /**
+ * @dataProvider dataPEM
+ */
+ public function testMeToPem(string $key)
+ {
+ Crypto::pemToMe($key, $m, $e);
+
+ $checkKey = Crypto::meToPem($m, $e);
+
+ $this->assertEquals($key, $checkKey);
+ }
}
/**