RSA 公钥格式转换之PHP实现


在.net中公钥的格式总是以modules 、exponent的格式存在的,但是openssl做加密、解密总是使用pem格式的,这里实现了前者到后者的格式转换。

.net生成的public key的格式:
<modulus>
jY39vkCL8xCrUK9eepK2SQ447xiU/bZmnJi6G+4ripHzOJ65YTsxJ3sEOrXCyb0P
MBXQchQ2xpE8g7PyHe4zv07/Q7hbRFJ2CJAIyFj7OD5aejOiIptMzPsYNMx5Gkbs
</modulus>
<exponent>
AQAB
</exponent>

<?php
/** 
 * Zeal Extends of ZendFramework 
 * 
 * @category   Zeal 
 * @package    Zeal 
 * @subpackage Security 
 */  
  
/** 
 * RSA公钥格式转化 
 * 
 * @category   Zeal 
 * @package    Zeal 
 * @subpackage Security 
 */  
class Zeal_Security_RSAPublicKey  
{  
    
/** 
     * ASN.1 type INTEGER class 
     */  
    
const ASN_TYPE_INTEGER 0x02;  
  
    
/** 
     * ASN.1 type BIT STRING class 
     */  
    
const ASN_TYPE_BITSTRING 0x03;  
  
    
/** 
     * ASN.1 type SEQUENCE class 
     */  
    
const ASN_TYPE_SEQUENCE 0x30;  
  
    
/** 
     * The Identifier for RSA Keys 
     */  
    
const RSA_KEY_IDENTIFIER '300D06092A864886F70D0101010500';  
  
    
/** 
     * Constructor  (disabled) 
     * 
     * @return void 
     */  
    
private function __construct()  
    {  
    }  
  
    
/** 
     * Transform an RSA Key in x.509 string format into a PEM encoding and 
     * return an PEM encoded string for openssl to handle 
     * 
     * @param string $certificate x.509 format cert string 
     * @return string The PEM encoded version of the key 
     */  
    
static public function getPublicKeyFromX509($certificate)  
    {  
        
$publicKeyString "-----BEGIN CERTIFICATE-----n" .  
                           
wordwrap($certificate64"n"true) .  
                           
"n-----END CERTIFICATE-----";  
  
        return 
$publicKeyString;  
    }  
  
    
/** 
     * Transform an RSA Key in Modulus/Exponent format into a PEM encoding and 
     * return an PEM encoded string for openssl to handle 
     * 
     * @param string $modulus The RSA Modulus in binary format 
     * @param string $exponent The RSA exponent in binary format 
     * @return string The PEM encoded version of the key 
     */  
    
static public function getPublicKeyFromModExp($modulus$exponent)  
    {  
        
$modulusInteger  self::_encodeValue($modulus,   
                                               
self::ASN_TYPE_INTEGER);  
        
$exponentInteger self::_encodeValue($exponent,   
                                               
self::ASN_TYPE_INTEGER);  
        
$modExpSequence  self::_encodeValue($modulusInteger .   
                                              
$exponentInteger,   
                                               
self::ASN_TYPE_SEQUENCE);  
        
$modExpBitString self::_encodeValue($modExpSequence,   
                                               
self::ASN_TYPE_BITSTRING);  
  
        
$binRsaKeyIdentifier pack"H*"self::RSA_KEY_IDENTIFIER );  
  
        
$publicKeySequence self::_encodeValue($binRsaKeyIdentifier .   
                                                
$modExpBitString,   
                                                 
self::ASN_TYPE_SEQUENCE);  
  
        
$publicKeyInfoBase64 base64_encode$publicKeySequence );  
  
        
$publicKeyString "-----BEGIN PUBLIC KEY-----n";  
        
$publicKeyString .= wordwrap($publicKeyInfoBase6464"n"true);  
        
$publicKeyString .= "n-----END PUBLIC KEY-----n";  
  
        return 
$publicKeyString;  
    }  
  
    
/** 
     * Encode a limited set of data types into ASN.1 encoding format 
     * which is used in X.509 certificates 
     * 
     * @param string $data The data to encode 
     * @param const $type The encoding format constant 
     * @return string The encoded value 
     * @throws Zend_InfoCard_Xml_Security_Exception 
     */  
    
static protected function _encodeValue($data$type)  
    {  
        
// Null pad some data when we get it  
        // (integer values > 128 and bitstrings)  
        
if( (($type == self::ASN_TYPE_INTEGER) && (ord($data) > 0x7f)) ||  
            (
$type == self::ASN_TYPE_BITSTRING)) {  
                
$data "�$data";  
        }  
  
        
$len strlen($data);  
  
        
// encode the value based on length of the string  
        
switch(true) {  
            case (
$len 128):  
                return 
sprintf("%c%c%s"$type$len$data);  
            case (
$len 0x0100):  
                return 
sprintf("%c%c%c%s"$type0x81$len$data);  
            case (
$len 0x010000):  
                return 
sprintf("%c%c%c%c%s"$type0x82,   
                                              
$len 0x0100,   
                                              
$len 0x0100$data);  
            default:  
                throw   
                  new 
Zeal_Security_RSAPublicKey_Exception("Could not encode value",1);  
        }  
  
        throw   
          new 
Zeal_Security_RSAPublicKey_Exception("Invalid code path",2);  
    }  
}  
  
class 
Zeal_Security_RSAPublicKey_Exception extends Exception  
{  
  
}

// example
 
$hCert openssl_pkey_get_public(  
            
Zeal_Security_RSAPublicKey::getPublicKeyFromModExp(  
                
file_get_contents("/home/zeal/certs/public.key"),  
                
"AQAB"  
            
)  
        );  
$dataToCheck "This is Data should be verified!";  
$signBinary ".................................";  
$ok openssl_verify(  
        
$dataToCheck,   
        
$signBinary,   
        
$hCert,  
        
OPENSSL_ALGO_SHA1  
);  
if (
$ok == 1) {  
    echo 
"good";  
}   
elseif (
$ok == 0) {  
    echo 
"bad";  
}   
else {  
    echo 
"error occured";  
}  
?>

留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据