3

RSA 公钥格式转换之PHP实现

 2 years ago
source link: https://blogread.cn/it/article/985?f=hot1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

RSA 公钥格式转换之PHP实现

浏览:4623次  出处信息

在.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($certificate, 64, "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($publicKeyInfoBase64, 64, "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", $type, 0x81, $len, $data);  
            case ($len < 0x010000):  
                return sprintf("%c%c%c%c%s", $type, 0x82,   
                                              $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";  
}  
?>

建议继续学习:

QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK