In cryptography, RC5 is a symmetric-key block cipher notable for its simplicity. Designed by Ronald Rivest in 1994.
RC5 encryption and decryption both expand the random key into 2(r+1) words that will be used sequentially (and only once each) during the encryption and decryption processes. All of the below comes from Rivest’s revised paper on RC5.
Source: https://en.wikipedia.org/wiki/RC5
We provide some function in PHP and Javascript.
PHP
The implementation is designed to work with w = 32, r = 12, and b = 16. It means that block size is 8 bytes ( 2×32 bits ) and key size is 16 bytes ( 128 bits ).
<?php /** * @author www.Tutorialspots.com * @copyright 2017 */ class RC5{ public static $S = array(); public static $r = 12; public static $w = 32; private static function cyclicShiftLeft($array, $positions) { $temp = array_slice($array, 0, $positions); $temp = array_merge(array_slice($array, $positions), $temp); return $temp; } private static function ROTL($v,$n,$m=32) { $y = sprintf("%0".$m."b",$v); $r = str_split($y); $r = self::cyclicShiftLeft($r,$n); return bindec(implode("",$r)) ; } private static function ROTR($v,$n,$m=32){ return self::ROTL($v,$m-$n,$m); } /* Key scheduling */ public static function rc5_init($K) { $b = 16; $u = self::$w/8; $c = max(1, ceil($b/$u)); $t = 2 * (self::$r+1); $L = array(); $P = 0xb7e15163; $Q = 0x9e3779b9; for($i = 0; $i < $b; $i++) $L[$i] = 0; for($i = $b-1, $L[$c-1] = 0; $i != -1; $i--) $L[$i/$u] = ($L[$i/$u] << 8) + $K[$i]; for(self::$S[0] = $P, $i = 1; $i < $t; $i++) self::$S[$i] = self::$S[$i-1] + $Q; $n = max($t,$c); for($A = $B = $i = $j = $k = 0; $k < 3 * $n; $k++, $i = ($i+1) % $t, $j = ($j+1) % $c) { $A = self::$S[$i] = self::ROTL(self::$S[$i] + ($A + $B), 3, self::$w); $B = $L[$j] = self::ROTL($L[$j] + ($A + $B), ($A + $B)&(self::$w-1), self::$w); } } public static function rc5_encrypt($pt) { $A = $pt[0] + self::$S[0]; $B = $pt[1] + self::$S[1]; for($i = 1; $i <= self::$r; $i++) { $A = self::ROTL($A ^ $B, $B&(self::$w-1), self::$w) + self::$S[2*$i]; $B = self::ROTL($B ^ $A, $A&(self::$w-1), self::$w) + self::$S[2*$i + 1]; } return array($A & (pow(2,self::$w)-1), $B & (pow(2,self::$w)-1)); } public static function rc5_decrypt($ct) { $B=$ct[1]; $A=$ct[0]; for($i = self::$r; $i > 0; $i--) { $B = self::ROTR($B - self::$S[2*$i + 1], $A&(self::$w-1), self::$w) ^ $A; $A = self::ROTR($A - self::$S[2*$i], $B&(self::$w-1), self::$w) ^ $B; } return array(($A - self::$S[0]) & (pow(2,self::$w)-1), ($B - self::$S[1]) & (pow(2,self::$w)-1)); } } ?>
Example:
RC5::rc5_init(array(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)); $enc = (RC5::rc5_encrypt( array(65,65) )); $dec = (RC5::rc5_decrypt( $enc )); var_dump($enc,$dec);
Result:
array(2) { [0]=> int(1927580246) [1]=> int(-516086777) } array(2) { [0]=> int(65) [1]=> int(65) }
Javascript
var RC5={ S : [], r : 12, w : 32, cyclicShiftLeft: function (array, positions) { var temp = array.slice(0, positions); temp = array.slice(positions).concat(temp); return temp; }, ROTL: function (v,n,m) { y = (v>=0?v:-1-v).toString(2); z = y.length; if(z < m) y = ("0".repeat(m-z))+y; r = y.split(""); if(r.length>m) r = r.slice(r.length-m); if(v<0) r = r.map(function(h){return h=="1"?"0":"1"}) r = this.cyclicShiftLeft(r,n); return parseInt(r.join(""),2) ; }, ROTR: function (v,n,m){ return this.ROTL(v,m-n,m); } , /* Key scheduling */ rc5_init: function (K) { var b = 16, u = this.w/8, c = Math.max(1, Math.ceil(b/u)), t = 2 * (this.r+1), L = [], P = 0xb7e15163, Q = 0x9e3779b9,i,j,k; for(i = 0; i < b; i++) L[i] = 0; for(i = b-1, L[c-1] = 0; i != -1; i--) L[Math.floor(i/u)] = (L[Math.floor(i/u)] << 8) + K[i]; for(this.S[0] = P, i = 1; i < t; i++) this.S[i] = this.S[i-1] + Q; var n = Math.max(t,c); for(A = B = i = j = k = 0; k < 3 * n; k++, i = (i+1) % t, j = (j+1) % c) { A = this.S[i] = this.ROTL(this.S[i] + (A + B), 3, this.w); B = L[j] = this.ROTL(L[j] + (A + B), (A + B)&(this.w-1), this.w); } }, rc5_encrypt: function (pt) { var A,B,i; A = pt[0] + this.S[0]; B = pt[1] + this.S[1]; for(i = 1; i <= this.r; i++) { A = this.ROTL(A ^ B, B&(this.w-1), this.w) + this.S[2*i]; B = this.ROTL(B ^ A, A&(this.w-1), this.w) + this.S[2*i + 1]; } return [A & (Math.pow(2,this.w)-1), B & (Math.pow(2,this.w)-1)]; }, rc5_decrypt: function (ct) { var A,B,i; B=ct[1]; A=ct[0]; for(i = this.r; i > 0; i--) { B = this.ROTR(B - this.S[2*i + 1], A&(this.w-1), this.w) ^ A; A = this.ROTR(A - this.S[2*i], B&(this.w-1), this.w) ^ B; } return [(A - this.S[0]) & (Math.pow(2,this.w)-1), (B - this.S[1]) & (Math.pow(2,this.w)-1)]; } }
Example:
RC5.rc5_init([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]); enc = (RC5.rc5_encrypt( [65,65] )); dec = (RC5.rc5_decrypt( enc )); console.log(enc,dec);
Result:
[1927580246, -516086777] [65, 65]
Part 2: RC5 block cipher implement in PHP and Javascript – part 2
1 Comment
RC5 block cipher implement in PHP and Javascript – part 2 | Free Online Tutorials
(February 12, 2017 - 2:00 pm)[…] Read part 1: RC5 block cipher implement in PHP and Javascript […]