169 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?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;
 | |
|     }    
 | |
| }
 |