<? Php /** * RSA Algorithm * Signature and ciphertext encoding: base64 string/hexadecimal string/binary string stream * Filling mode: PKCS1Padding (encryption and decryption)/NOPadding (decryption) * * Notice: Only accepts a single block. Block size is equal to the RSA key size! * If the key length is 1024 bits, the encrypted data size must be less than 128 bytes, And the PKCS1Padding's own 11 bytes. Therefore, the plaintext length must be less than 117 bytes. * * @ Author: linvo * @ Version: 1.0.0 * @ Date: 2013/1/23 */ Class RSA { Private $ pubKey = null; Private $ priKey = null; /** * Custom error handling */ Private function _ error ($ msg ){ Die ('rsa Error: '. $ msg); // TODO } /** * Constructor * * @ Param string public key file (passed during signature verification and encryption) * @ Param string private key file (input during signature and decryption) */ Public function _ construct ($ public_key_file = '', $ private_key_file = ''){ If ($ public_key_file ){ $ This-> _ getPublicKey ($ public_key_file ); } If ($ private_key_file ){ $ This-> _ getPrivateKey ($ private_key_file ); } } /** * Generate a signature * * @ Param string signature Material * @ Param string signature encoding (base64/hex/bin) * @ Return signature Value */ Public function sign ($ data, $ code = 'base64 '){ $ Ret = false; If (openssl_sign ($ data, $ ret, $ this-> priKey )){ $ Ret = $ this-> _ encode ($ ret, $ code ); } Return $ ret; } /** * Verify the signature * * @ Param string signature Material * @ Param string signature Value * @ Param string signature encoding (base64/hex/bin) * @ Return bool */ Public function verify ($ data, $ sign, $ code = 'base64 '){ $ Ret = false; $ Sign = $ this-> _ decode ($ sign, $ code ); If ($ sign! = False ){ Switch (openssl_verify ($ data, $ sign, $ this-> pubKey )){ Case 1: $ ret = true; break; Case 0: Case-1: Default: $ ret = false; } } Return $ ret; } /** * Encryption * * @ Param string plaintext * @ Param string ciphertext encoding (base64/hex/bin) * @ Param int fill mode (it seems that php has a bug, so currently only OPENSSL_PKCS1_PADDING is supported) * @ Return string ciphertext */ Public function encrypt ($ data, $ code = 'base64', $ padding = OPENSSL_PKCS1_PADDING ){ $ Ret = false; If (! $ This-> _ checkPadding ($ padding, 'en') $ this-> _ error ('padding error '); If (openssl_public_encrypt ($ data, $ result, $ this-> pubKey, $ padding )){ $ Ret = $ this-> _ encode ($ result, $ code ); } Return $ ret; } /** * Decryption * * @ Param string ciphertext * @ Param string ciphertext encoding (base64/hex/bin) * @ Param int fill mode (OPENSSL_PKCS1_PADDING/OPENSSL_NO_PADDING) * @ Param bool whether to flip the plaintext (When passing Microsoft CryptoAPI-generated RSA cyphertext, revert the bytes in the block) * @ Return string plaintext */ Public function decrypt ($ data, $ code = 'base64', $ padding = OPENSSL_PKCS1_PADDING, $ rev = false ){ $ Ret = false; $ Data = $ this-> _ decode ($ data, $ code ); If (! $ This-> _ checkPadding ($ padding, 'de') $ this-> _ error ('padding error '); If ($ data! = False ){ If (openssl_private_decrypt ($ data, $ result, $ this-> priKey, $ padding )){ $ Ret = $ rev? Rtrim (strrev ($ result), "\ 0"): ''. $ result; } } Return $ ret; } // Private Method /** * Check Filling Type * Encryption only supports PKCS1_PADDING. * Supports PKCS1_PADDING and NO_PADDING for decryption. * * @ Param int fill Mode * @ Param string encrypt en/decrypt de * @ Return bool */ Private function _ checkPadding ($ padding, $ type ){ If ($ type = 'en '){ Switch ($ padding ){ Case OPENSSL_PKCS1_PADDING: $ Ret = true; Break; Default: $ Ret = false; } } Else { Switch ($ padding ){ Case OPENSSL_PKCS1_PADDING: Case OPENSSL_NO_PADDING: $ Ret = true; Break; Default: $ Ret = false; } } Return $ ret; } Private function _ encode ($ data, $ code ){ Switch (strtolower ($ code )){ Case 'base64 ': $ Data = base64_encode (''. $ data ); Break; Case 'hex ': $ Data = bin2hex ($ data ); Break; Case 'bin ': Default: } Return $ data; } Private function _ decode ($ data, $ code ){ Switch (strtolower ($ code )){ Case 'base64 ': $ Data = base64_decode ($ data ); Break; Case 'hex ': $ Data = $ this-> _ hex2bin ($ data ); Break; Case 'bin ': Default: } Return $ data; } Private function _ getPublicKey ($ file ){ $ Key_content = $ this-> _ readFile ($ file ); If ($ key_content ){ $ This-> pubKey = openssl_get_publickey ($ key_content ); } } Private function _ getPrivateKey ($ file ){ $ Key_content = $ this-> _ readFile ($ file ); If ($ key_content ){ $ This-> priKey = openssl_get_privatekey ($ key_content ); } } Private function _ readFile ($ file ){ $ Ret = false; If (! File_exists ($ file )){ $ This-> _ error ("The file {$ file} is not exists "); } Else { $ Ret = file_get_contents ($ file ); } Return $ ret; } Private function _ hex2bin ($ hex = false ){ $ Ret = $ hex! = False & preg_match ('/^ [0-9a-fA-F] + $/I', $ hex )? Pack ("H *", $ hex): false; Return $ ret; } } |