技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 算法 --> RSA 公钥格式转换之PHP实现

RSA 公钥格式转换之PHP实现

浏览:4999次  出处信息
在.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"
;  
}  
?>

建议继续学习:

  1. 为什么要用公钥/私钥而不是密码去做SSH身份验证    (阅读:4696)
  2. 公钥私钥加密解密数字证书数字签名详解    (阅读:4013)
  3. 跨越千年的RSA算法    (阅读:2988)
  4. 数论的应用-RSA公钥算法    (阅读:2586)
  5. RSA 算法是如何诞生的    (阅读:1829)
  6. 密码学及公钥基础设施入门    (阅读:1180)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1