Implementation of RSA algorithm under PHP

Source: Internet
Author: User
Tags foreach array assert chr modulus string format strlen
/*
* Implementation of the RSA algorithm
* (C) Copyright Edsko de Vries, Ireland
*
* Licensed under the GNU public License (GPL)
*
* This implementation has been verified against [3]
* (tested java/php interoperability).
*
* References:
* [1] "Applied Cryptography", Bruce Schneier, John Wiley & Sons, 1996
* [2] "Prime number hide-and-seek", Brian Raiter, Muppetlabs (online)
* [3] "The bouncy Castle Crypto Package" Legion bouncy of the Castle,
* (Open Source Cryptography Library for Java, online)
* [4] "PKCS #1: RSA Encryption Standard", RSA Laboratories technical Note,
* Version 1.5, revised November 1, 1993
*/

/*
* Functions that are meant to is used by the user of this PHP module.
*
* Notes:
*-$key and $modulus should is numbers in (decimal) string format
*-$message is expected to binary data
*-$keylength should be a multiple of 8, and should is in bits
*-For Rsa_encrypt/rsa_sign, the length of $message should not exceed
* ($keylength/8)-one (as mandated by [4]).
*-Rsa_encrypt and rsa_sign'll automatically add padding to the message.
* For Rsa_encrypt, this padding would consist of random values; For Rsa_sign,
* Padding would consist of the appropriate number of 0xFF values ([4])
*-Rsa_decrypt and rsa_verify'll automatically remove message padding.
*-Blocks for decoding (Rsa_decrypt, rsa_verify) should is exactly
* ($keylength/8) bytes long.
*-Rsa_encrypt and rsa_verify expect a public key; Rsa_decrypt and Rsa_sign
* Expect a private key.
*/

function Rsa_encrypt ($message, $public _key, $modulus, $keylength)
{
$padded = Add_pkcs1_padding ($message, True, $keylength/8);
$number = Binary_to_number ($padded);
$encrypted = Pow_mod ($number, $public _key, $modulus);
$result = Number_to_binary ($encrypted, $keylength/8);

return $result;
}

function Rsa_decrypt ($message, $private _key, $modulus, $keylength)
{
$number = Binary_to_number ($message);
$decrypted = Pow_mod ($number, $private _key, $modulus);
$result = Number_to_binary ($decrypted, $keylength/8);

Return remove_pkcs1_padding ($result, $keylength/8);
}

function Rsa_sign ($message, $private _key, $modulus, $keylength)
{
$padded = Add_pkcs1_padding ($message, False, $keylength/8);
$number = Binary_to_number ($padded);
$signed = Pow_mod ($number, $private _key, $modulus);
$result = Number_to_binary ($signed, $keylength/8);

return $result;
}

function Rsa_verify ($message, $public _key, $modulus, $keylength)
{
Return Rsa_decrypt ($message, $public _key, $modulus, $keylength);
}

/*
* Some Constants
*/

Define ("Bccomp_larger", 1);

/*
* The actual implementation.
* Requires Bcmath Support in PHP (compile with--enable-bcmath)
*/

//--
Calculate (p ^ q) mod R
//
We need some trickery to [2]:
(a) Avoid calculating (p ^ q) before (p ^ q) mod R, because for typical RSA
Applications, (p ^ q) is going to be _way_ too large.
(I mean, __way__ too large-won ' t fit in your computer ' s memory.)
(b) still be reasonably efficient.
//
We assume P, Q and R are all positive, and that R is Non-zero.
//
The more simple algorithm of multiplying $p by itself $q times, and
Applying "mod $r" at every-also-valid, but is O ($q), whereas
Algorithm is O (log $q). Big difference.
//
As far as I can, the algorithm I use is optimal; There is no redundancy
In the calculation of the partial results.
//--
function Pow_mod ($p, $q, $r)
{
Extract powers of 2 from $q
$factors = Array ();
$div = $q;
$power _of_two = 0;
while (Bccomp ($div, "0") = = Bccomp_larger)
{
$rem = Bcmod ($div, 2);
$div = Bcdiv ($div, 2);

if ($rem) Array_push ($factors, $power _of_two);
$power _of_two++;
}

Calculate partial results for each factor with the using each partial result as a
Starting point for the next. This depends of the factors of two being
Generated in increasing order.
$partial _results = Array ();
$part _res = $p;
$idx = 0;
foreach ($factors as $factor)
{
while ($idx < $factor)
{
$part _res = Bcpow ($part _res, "2");
$part _res = Bcmod ($part _res, $r);

$idx + +;
}

Array_pus ($partial _results, $part _res);
}

Calculate Final Result
$result = "1";
foreach ($partial _results as $part _res)
{
$result = Bcmul ($result, $part _res);
$result = Bcmod ($result, $r);
}

return $result;
}

//--
Function to add padding to a decrypted string
We need to know if it is a private or a public key operation [4]
//--
function add_pkcs1_padding ($data, $isPublicKey, $blocksize)
{
$pad _length = $blocksize-3-strlen ($data);

if ($isPublicKey)
{
$block _type = "\x02";

$padding = "";
for ($i = 0; $i < $pad _length; $i + +)
{
$rnd = Mt_rand (1, 255);
$padding. = Chr ($RND);
}
}
Else
{
$block _type = "\x01";
$padding = Str_repeat ("\xff", $pad _length);
}

Return "\x00". $block _type. $padding. "\x00". $data;
}

//--
Remove padding from a decrypted string
[4] for more details.
//--
function remove_pkcs1_padding ($data, $blocksize)
{
ASSERT (strlen ($data) = = $blocksize);
$data = substr ($data, 1);

We cannot deal with block type 0
if ($data {0} = = ' a ')
Die ("block type 0 not implemented.");

Then The block type must is 1 or 2
Assert (($data {0} = = "\x01") | | ($data {0} = = "\x02"));

Remove the padding
$offset = Strpos ($data, "n", 1);
Return substr ($data, $offset + 1);
}

//--
Convert binary data to a decimal number
//--
function Binary_to_number ($data)
{
$base = "256";
$radix = "1";
$result = "0";

for ($i = strlen ($data)-1; $i >= 0; $i--)
{
$digit = Ord ($data {$i});
$part _res = Bcmul ($digit, $radix);
$result = Bcadd ($result, $part _res);
$radix = Bcmul ($radix, $base);
}

return $result;
}

//--
Convert a number back into binary form
//--
function Number_to_binary ($number, $blocksize)
{
$base = "256";
$result = "";

$div = $number;
while ($div > 0)
{
$mod = Bcmod ($div, $base);
$div = Bcdiv ($div, $base);

$result = Chr ($mod). $result;
}

Return Str_pad ($result, $blocksize, "\x00", str_pad_left);
}
?>

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.