helper functions for Diaspora cert mangling
This commit is contained in:
		
							
								
								
									
										52
									
								
								include/certfns.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								include/certfns.php
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||||
|  | }	 | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										172
									
								
								library/ASNValue.class.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								library/ASNValue.class.php
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||||
|  |     }     | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ?> | ||||||
		Reference in New Issue
	
	Block a user