fr34k Posted March 6, 2010 Share Posted March 6, 2010 I made a small-bit RSA class in PHP to play with the RSA algorithm (not for any real application.) It was built with a 16-bit key in mind. However, I want to expand on it. Ultimately, I'd like to be able to dynamically specify a key's bit size. I'm pretty sure the problem lies in the packing/unpacking, because it seems to work great as long as the key is 16-bits and it's packed and unpacked as unsigned short (16-bit) integers. Any help would be immensely appreciated! error_reporting(E_ALL); ini_set("display_errors", 1); class rsa { private $e, $d, $n, $p, $primes, $phi, $q; function __construct() { $bits = 16; $floor = gmp_sqrt(gmp_pow(2, $bits - 1)); $ceiling = gmp_sqrt(gmp_pow(2, $bits)); $currentPrime = gmp_nextprime($floor); while (gmp_cmp($currentPrime, $ceiling) < 0) { $this->primes[] = gmp_intval($currentPrime); $currentPrime = gmp_nextprime($currentPrime); } $this->reset(); } function dec($cipherText = '') { $unpackedCipherText = unpack('S*', $cipherText); $unpackedCipherTextLength = count($unpackedCipherText); $outputString = ''; for ($i = 1; $i <= $unpackedCipherTextLength; $i++) $outputString .= pack('S*', gmp_intval(gmp_powm($unpackedCipherText[$i], $this->d, $this->n))); return $outputString; } function enc($plainText = '') { $unpackedText = unpack('S*', $plainText); $unpackedTextLength = count($unpackedText); $outputString = ''; for ($i = 1; $i <= $unpackedTextLength; $i++) $outputString .= pack('S*', gmp_intval(gmp_powm($unpackedText[$i], $this->e, $this->n))); return $outputString; } function reset() { $this->e = 3; do { $this->setup(); } while(gmp_cmp(gmp_gcd($this->e, $this->phi), 1) != 0 && gmp_cmp($this->e, $this->phi) < 0); $this->d = gmp_invert($this->e, $this->phi); } function setup() { $randomPrimes = array_rand($this->primes, 2); $this->p = $this->primes[$randomPrimes[0]]; $this->q = $this->primes[$randomPrimes[1]]; $this->n = gmp_mul($this->p, $this->q); $this->phi = gmp_mul(($this->p - 1), ($this->q - 1)); $this->e = gmp_intval(gmp_nextprime($this->e)); } } $testRSA = new rsa(); $testText = 'The quick brown fox jumps over the lazy dog.'; $cipherText = $testRSA->enc($testText); print 'Enc: '.$cipherText.'<br />'; print 'Dec: '.$testRSA->dec($cipherText); This code is modified from my original. You can alter the key size in the constructor and the parameters for the four packs/unpacks. I think that this is all that needs to be edited to achieve my goal. Lastly, it utilizes PHP's GMP extension, because PHP's standard math capabilities weren't cutting it. Also, there aren't as many fail-safes in there as I'd like, so there is the remote possibility that it'll fail, every now and again. Link to comment https://forums.phpfreaks.com/topic/194308-altering-rsa-code-for-variable-key-length/ Share on other sites More sharing options...
fr34k Posted March 7, 2010 Author Share Posted March 7, 2010 The root of my problem seems to stem from PHP's limited number capabilities. For instance, my PHP installation only uses thirty-two bits for integers. Once you go over that (or even up to it, in some cases,) crazy things start to happen. That was ruining my routines. This can probably be fixed by writing a custom pack function with GMP, but I am not going to take it that far. That being said, I have modified the script to allow variable bit lengths as per PHP's capabilities. Again, there really aren't any checks or validation in here. It's pretty bare bones stuff. class rsa { private $e, $d, $n, $p, $primes, $phi, $q; function __construct($bits = 16, $d = false, $e = false, $n = false) { if ($bits > PHP_INT_SIZE * $bits = (PHP_INT_SIZE * - 1; $floor = gmp_sqrt(gmp_pow(2, $bits - 1)); $ceiling = gmp_sqrt(gmp_pow(2, $bits)); $currentPrime = gmp_nextprime($floor); while (gmp_cmp($currentPrime, $ceiling) < 0) { $this->primes[] = gmp_strval($currentPrime); $currentPrime = gmp_nextprime($currentPrime); } if ($d !== false && $e !== false && $n !== false) { $this->d = gmp_init($d); $this->e = gmp_init($e); $this->n = gmp_init($n); } else $this->reset(); } function dec($cipherText = '') { $unpackedCipherText = unpack('I*', $cipherText); $unpackedCipherTextLength = count($unpackedCipherText); $outputString = ''; for ($i = 1; $i <= $unpackedCipherTextLength; $i++) $outputString .= pack('S*', gmp_strval(gmp_powm($unpackedCipherText[$i], $this->d, $this->n), 10)); return $outputString; } function enc($plainText = '') { $unpackedText = unpack('S*', $plainText); $unpackedTextLength = count($unpackedText); $outputString = ''; for ($i = 1; $i <= $unpackedTextLength; $i++) $outputString .= pack('I*', gmp_strval(gmp_powm($unpackedText[$i], $this->e, $this->n), 10)); return $outputString; } function get_private() { return gmp_strval($this->d); } function get_public() { return gmp_strval($this->e); } function get_mod() { return gmp_strval($this->n); } function reset() { $this->e = 3; do { $this->setup(); } while(gmp_cmp(gmp_gcd($this->e, $this->phi), 1) != 0 && gmp_cmp($this->e, $this->phi) < 0); $this->d = gmp_invert($this->e, $this->phi); } function setup() { $randomPrimes = array_rand($this->primes, 2); $this->p = $this->primes[$randomPrimes[0]]; $this->q = $this->primes[$randomPrimes[1]]; $this->n = gmp_mul($this->p, $this->q); $this->phi = gmp_mul(($this->p - 1), ($this->q - 1)); $this->e = gmp_nextprime($this->e); } } $testRSA = new rsa(30); $testText = 'The quick brown fox jumps over the lazy dog.'; $cipherText = $testRSA->enc($testText); print 'Enc: '.htmlentities($cipherText).'<br />'; print 'Dec: '.$testRSA->dec($cipherText); Link to comment https://forums.phpfreaks.com/topic/194308-altering-rsa-code-for-variable-key-length/#findComment-1022537 Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.