SHARE

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
*/

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]

Try it yourself