IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

RSA 公钥格式转换之PHP实现

PHPor 的Blog 2010-01-18 12:11:47 累计浏览 5,955 次
本机暂存
在.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. Windows 95 defenses against installers that overwrite a file with an older version (2026-03-25 07:04:03)
  2. 提权实录:通过命名管道劫持可写服务 (2026-03-16 00:00:00)
  3. 黑盒视角下的 WebView 漏洞面探索 (2025-12-26 00:00:00)

查看更多 安全 文章 →

建议继续学习

  1. 使用gettext来支持PHP的多语言 (累计阅读 39,197)
  2. WordPress插件开发 -- 在插件使用数据库存储数据 (累计阅读 29,098)
  3. Paypal接口详细代码(PHP版,非API接口) (累计阅读 19,353)
  4. 我的PHP,Python和Ruby之路 (累计阅读 13,075)
  5. include(“./file.php”)和include(“file.php”)区别 (累计阅读 12,732)
  6. 15个最好的免费开源电子商务平台 (累计阅读 12,473)
  7. Redis消息队列的若干实现方式 (累计阅读 12,012)
  8. 到底什么是MVC? (累计阅读 11,724)
  9. 整理了一份招PHP高级工程师的面试题 (累计阅读 11,510)
  10. Rolling cURL: PHP并发最佳实践 (累计阅读 11,433)