aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/certfns.php52
-rw-r--r--library/ASNValue.class.php172
2 files changed, 224 insertions, 0 deletions
diff --git a/include/certfns.php b/include/certfns.php
new file mode 100644
index 000000000..70d2b54a0
--- /dev/null
+++ b/include/certfns.php
@@ -0,0 +1,52 @@
+<?php
+
+require_once('library/ASNValue.class.php');
+
+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;
+}
+
+function pkcs8_encode($Modulus,$PublicExponent) {
+ //Encode key sequence
+ $modulus = new ASNValue(ASNValue::TAG_INTEGER);
+ $modulus->SetIntBuffer($Modulus);
+ $publicExponent = new ASNValue(ASNValue::TAG_INTEGER);
+ $publicExponent->SetInt($PublicExponent);
+ $keySequenceItems = array($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;
+}
+
+
+function metopem($m,$e) {
+ $der = pkcs8_emcode($m,$e);
+ $key = DerToPem($der,true);
+ return $key;
+}
+
+
diff --git a/library/ASNValue.class.php b/library/ASNValue.class.php
new file mode 100644
index 000000000..8a6aced97
--- /dev/null
+++ b/library/ASNValue.class.php
@@ -0,0 +1,172 @@
+<?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;
+ }
+}
+
+
+?>