converting c method that uses bitwise to php - php

I'm trying to convert an APR (apache runtime) method to PHP, but I can't quite figure it out.
The method creates a string that is a directory path and file - so example output would be A/B/C/[a-fA-F0-9_#]. It's using bitwise operations on a binary string returned from md5($string,true); When I run the php below, I get:
array (
0 => 'A',
1 => '/',
2 => 'A',
3 => '/',
4 => 'A',
5 => '/',
6 => 'AAAAAAAAAAAAAAAAAAA',
)
What am I doing wrong? Is this not possible due to how PHP internally represents char arrays?
Here is the c method:
static void cache_hash(const char *it, char *val, int ndepth, int nlength)
{
apr_md5_ctx_t context;
unsigned char digest[16];
char tmp[22];
int i, k, d;
unsigned int x;
static const char enc_table[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_#";
apr_md5_init(&context);
apr_md5_update(&context, (const unsigned char *) it, strlen(it));
apr_md5_final(digest, &context);
/* encode 128 bits as 22 characters, using a modified uuencoding
* the encoding is 3 bytes -> 4 characters* i.e. 128 bits is
* 5 x 3 bytes + 1 byte -> 5 * 4 characters + 2 characters
*/
for (i = 0, k = 0; i < 15; i += 3) {
x = (digest[i] << 16) | (digest[i + 1] << 8) | digest[i + 2];
tmp[k++] = enc_table[x >> 18];
tmp[k++] = enc_table[(x >> 12) & 0x3f];
tmp[k++] = enc_table[(x >> 6) & 0x3f];
tmp[k++] = enc_table[x & 0x3f];
}
/* one byte left */
x = digest[15];
tmp[k++] = enc_table[x >> 2]; /* use up 6 bits */
tmp[k++] = enc_table[(x << 4) & 0x3f];
/* now split into directory levels */
for (i = k = d = 0; d < ndepth; ++d) {
memcpy(&val[i], &tmp[k], nlength);
k += nlength;
val[i + nlength] = '/';
i += nlength + 1;
}
memcpy(&val[i], &tmp[k], 22 - k);
val[i + 22 - k] = '\0';
}
Here is my attempt at converting to PHP:
$URL = 'thumbnail.php?u=http%3A%2F%2Fwww.google.com%2Flogos%2Fclassicplus.png&w=200';
cache_hash($URL, $theFile);
function cache_hash($URL, &$theFile, $dirlevels = 3, $dirlength = 1)
{
$enc_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_#";
$md5URL = md5($URL,true);
// echo "MD5URL: ".var_export($md5URL,true);
//$md5URL = digest
$tmp = '0000000000000000000000'; //22 chars
for ($i = 0; $i < 22; $i++) {
$tmp[$i] = 0x0;
}
var_export(unpack('S',$md5URL));
p(ord($md5URL[0]));
p(ord($md5URL[1]));
/* encode 128 bits as 22 characters, using a modified uuencoding
* the encoding is 3 bytes -> 4 characters* i.e. 128 bits is
* 5 x 3 bytes + 1 byte -> 5 * 4 characters + 2 characters
*/
for ($i = 0, $k = 0; $i < 15; $i += 3) {
// p($md5URL[$i] << 16);
// p($md5URL[$i + 1] << 8);
// p($md5URL[$i + 2]);
$x = ($md5URL[$i] << 16) | ($md5URL[$i + 1] << 8) | $md5URL[$i + 2];
// p($x);
p($x >> 18);
$tmp[$k++] = $enc_table[$x >> 18];
$tmp[$k++] = $enc_table[($x >> 12) & 0x3f];
$tmp[$k++] = $enc_table[($x >> 6) & 0x3f];
$tmp[$k++] = $enc_table[$x & 0x3f];
}
/* one byte left */
$x = $md5URL[15];
$tmp[$k++] = $enc_table[$x >> 2]; /* use up 6 bits */
$tmp[$k++] = $enc_table[($x << 4) & 0x3f];
/* now split into directory levels */
for ($i = $k = $d = 0; $d < $dirlevels; ++$d) {
var_export($tmp);
$theFile[$i] = substr($tmp,$k,$dirlength);
$k += $dirlength;
$theFile[$i + $dirlength] = '/';
$i += $dirlength + 1;
}
$theFile[$i] = substr($tmp,$k,22 - $k);
var_export($theFile);
}
function p($val) {
echo " Dec:\n";
printf(' val= %d', ord($val));
echo "\nBinary:\n";
printf(' val= %b', ord($val));
echo "\n";
}

change the two lines, it should work I believe
$x = (ord($md5URL[$i]) << 16) | (ord($md5URL[$i + 1]) << 8) | ord($md5URL[$i + 2]);
$x = ord($md5URL[15]);
I think you have to change this line too:
$md5URL = md5($URL, false);

Related

CRC Maxim/Dallas 1Wire Generation: translate Visual Basic to PHP

i Need a function that generates the Maxim/Dallas 1-Wire CRC 8bit-Code like this page:
http://www.datastat.com/sysadminjournal/maximcrc.cgi
For that problem I found an little Excel Calculator for solution.
It works correctly, but I got the Problem to translate it into PHP language.
Original VB Code:
Private Sub ROMCRC_Click()
Dim InHex, OutBinStr As String
Dim OutBinArr(1 To 56) As Integer
Dim OutDec, i, CRC(1 To 8), CRCTemp As Integer
InHex = Range("ROMByte1").Value & Range("ROMByte2").Value & Range("ROMByte3").Value & Range("ROMByte4").Value & Range("ROMByte5").Value & Range("ROMByte6").Value & Range("ROMByte7").Value
OutBinStr = HexToBin(InHex)
' Convert string to array, LSB = OutBinArr(1)
For i = 1 To 56
OutBinArr(57 - i) = Mid$(OutBinStr, i, 1) ' Split(OutBinStr)
Next i
'Initialize CRC
For i = 1 To 8
CRC(i) = 0
Next i
'Calculate CRC
For i = 1 To 56
CRCTemp = CRC(1) Xor OutBinArr(i)
CRC(1) = CRC(2)
CRC(2) = CRC(3)
CRC(3) = CRC(4) Xor CRCTemp
CRC(4) = CRC(5) Xor CRCTemp
CRC(5) = CRC(6)
CRC(6) = CRC(7)
CRC(7) = CRC(8)
CRC(8) = CRCTemp
Next i
DecCRC = BinToDec(CRC)
Range("ROMCRCValue").Value = DecCRC
End Sub
Private Function HexToBin(hstr)
'convert hex string to binary string
cnvarr = Array("0000", "0001", "0010", "0011", _
"0100", "0101", "0110", "0111", "1000", _
"1001", "1010", "1011", "1100", "1101", _
"1110", "1111")
bstr = ""
For i = 1 To Len(hstr)
hdgt = Mid(hstr, i, 1)
cix = CInt("&H" & hdgt)
bstr = bstr & cnvarr(cix)
Next
HexToBin = bstr
End Function
Function BinToDec(bstr)
'convert 8 bit Binary number to Decimal
Dim j, Out As Integer
Out = 0
For j = 1 To 8
Out = Out + bstr(j) * 2 ^ (j - 1)
Next j
BinToDec = Out
End Function
My PHP test code:
protected function HexToBin($hstr) {
//convert hex string to binary string
$cnvarr = array(
'0000',
'0001',
'0010',
'0011',
'0100',
'0101',
'0110',
'0111',
'1000',
'1001',
'1010',
'1011',
'1100',
'1101',
'1110',
'1111'
);
$bstr = "";
for ($i = 1; $i <= strlen($hstr); $i++) {
$hdgt = substr($hstr, $i, 1);
$cix = intval($hdgt);
echo $cix.'|';
$bstr .= $cnvarr[$cix];
}
return $bstr;
}
protected function createHash($data) {
//$OutBinStr = $this->HexToBin($data);
$OutBinStr = hex2bin($data);
$OutBinArr = array();
$crc = array();
//Convert string to array, LSB = OutBinArr(1)
for ($i = 1; $i <= 56; $i++) {
$OutBinArr[57 - $i] = substr($OutBinStr, $i - 1, 1);
}
//initialize crc
for ($i = 1; $i <= 8; $i++) {
$crc[$i] = 0;
}
// calculate
for ($i = 1; $i <= 56; $i++) {
$CRCTemp = $crc[1] ^ $OutBinArr[$i];
$crc[1] = $crc[2];
$crc[2] = $crc[3];
$crc[3] = $crc[4] ^ $CRCTemp;
$crc[4] = $crc[5] ^ $CRCTemp;
$crc[5] = $crc[6];
$crc[6] = $crc[7];
$crc[7] = $crc[8];
$crc[8] = $CRCTemp;
}
return implode('', $crc);
}
Example call:
$buttonId = '0000145D6E0F01';
echo $this->createHash($buttonId);
I thank you if you have any Ideas why the Script does not generate the correct crc.
Thank you, nice regards
Michael
Your HexToBin() was generating wrong string. The for loop for substr() started with 1 instead of 0. See substr manual.
Imploding $crc resulted an reverse bit order value.
<?PHP
function HexToBin($hstr){
$hstr = str_replace(' ','',$hstr);
$hArr = str_split($hstr);
$bstr = "";
foreach($hArr AS $c){
$cix = sprintf("0x0{$c}");
// echo sprintf("%04b|",hexdec($cix));
$bstr .= sprintf("%04b",hexdec($cix));
}
return $bstr;
}
function createHash($data){
$OutBinStr = HexToBin($data);
$crc = array_fill(0,8,0);
$OutBinArr = array_reverse(str_split($OutBinStr));
// calculate
foreach($OutBinArr AS $i){
$CRCTemp = $crc[0] ^ $i;
$crc[0] = $crc[1];
$crc[1] = $crc[2];
$crc[2] = $crc[3] ^ $CRCTemp;
$crc[3] = $crc[4] ^ $CRCTemp;
$crc[4] = $crc[5];
$crc[5] = $crc[6];
$crc[6] = $crc[7];
$crc[7] = $CRCTemp;
}
$crc = array_reverse($crc);
return implode('', $crc);
}
$buttonId = '00 00 14 5D 6E 0F 01'; // 59 => 3B
// $buttonId = '12 AA 12 5F 14 A2 12 12'; // 109 => 6D
$crc = bindec(createHash($buttonId));
printf("\n%d => %X",$crc,$crc);
?>

How to encrypt/decrypt an integer in PHP

is there any way to make 2 way encryption/decryption for an integer (or string)
Please note that I am not looking for encoding
i need something like this
crypting (100) --> 24694
crypting (101) --> 9564jh4 or 45216 or gvhjdfT or whatever ...
decrypting (24694) --> 100
I don't need encoding because it`s bijective
base64_encode(100) -->MTAw
base64_encode(101) -->MTAx
I hope I will find a way here to encrypt/decrypt PURE NUMBERS (computer love numbers, it's faster)
function decrypt($string, $key) {
$result = '';
$string = base64_decode($string);
for($i=0; $i<strlen($string); $i++) {
$char = substr($string, $i, 1);
$keychar = substr($key, ($i % strlen($key))-1, 1);
$char = chr(ord($char)-ord($keychar));
$result.=$char;
}
return $result;
}
function encrypt($string, $key) {
$result = '';
for($i=0; $i<strlen($string); $i++) {
$char = substr($string, $i, 1);
$keychar = substr($key, ($i % strlen($key))-1, 1);
$char = chr(ord($char)+ord($keychar));
$result.=$char;
}
return base64_encode($result);
}
Have you tried looking into ROT-13?
More serious answer: from this SO answer, you can use:
function numhash($n) {
return (((0x0000FFFF & $n) << 16) + ((0xFFFF0000 & $n) >> 16));
}
numhash(42); // 2752512
numhash(numhash(42)); // 42
64bit support. negative number support. and a little bit security salt.
#Petr Cibulka
class NumHash {
private static $SALT = 0xd0c0adbf;
public static function encrypt($n) {
return (PHP_INT_SIZE == 4 ? self::encrypt32($n) : self::encrypt64($n)) ^ self::$SALT;
}
public static function decrypt($n) {
$n ^= self::$SALT;
return PHP_INT_SIZE == 4 ? self::decrypt32($n) : self::decrypt64($n);
}
public static function encrypt32($n) {
return ((0x000000FF & $n) << 24) + (((0xFFFFFF00 & $n) >> 8) & 0x00FFFFFF);
}
public static function decrypt32($n) {
return ((0x00FFFFFF & $n) << 8) + (((0xFF000000 & $n) >> 24) & 0x000000FF);
}
public static function encrypt64($n) {
/*
echo PHP_EOL . $n . PHP_EOL;
printf("n :%20X\n", $n);
printf("<< :%20X\n", (0x000000000000FFFF & $n) << 48);
printf(">> :%20X\n", (0xFFFFFFFFFFFF0000 & $n) >> 16);
printf(">>& :%20X\n", ((0xFFFFFFFFFFFF0000 & $n) >> 16) & 0x0000FFFFFFFFFFFF);
printf("= :%20X\n", ((0x000000000000FFFF & $n) << 48) + (((0xFFFFFFFFFFFF0000 & $n) >> 16) & 0x0000FFFFFFFFFFFF));
/* */
return ((0x000000000000FFFF & $n) << 48) + (((0xFFFFFFFFFFFF0000 & $n) >> 16) & 0x0000FFFFFFFFFFFF);
}
public static function decrypt64($n) {
/*
echo PHP_EOL;
printf("n :%20X\n", $n);
printf("<< :%20X\n", (0x0000FFFFFFFFFFFF & $n) << 16);
printf(">> :%20X\n", (0xFFFF000000000000 & $n) >> 48);
printf(">>& :%20X\n", ((0xFFFF000000000000 & $n) >> 48) & 0x000000000000FFFF);
printf("= :%20X\n", ((0x0000FFFFFFFFFFFF & $n) << 16) + (((0xFFFF000000000000 & $n) >> 48) & 0x000000000000FFFF));
/* */
return ((0x0000FFFFFFFFFFFF & $n) << 16) + (((0xFFFF000000000000 & $n) >> 48) & 0x000000000000FFFF);
}
}
var_dump(NumHash::encrypt(42));
var_dump(NumHash::encrypt(NumHash::encrypt(42)));
var_dump(NumHash::decrypt(NumHash::encrypt(42)));
echo PHP_EOL;
// stability test
var_dump(NumHash::decrypt(NumHash::encrypt(0)));
var_dump(NumHash::decrypt(NumHash::encrypt(-1)));
var_dump(NumHash::decrypt(NumHash::encrypt(210021200651)));
var_dump(NumHash::decrypt(NumHash::encrypt(210042420501)));
Here's the step by step(remove the comments):
210042420501
n : 30E780FD15
<< : FD15000000000000
>> : 30E780
>>& : 30E780
= : FD1500000030E780
n : FD1500000030E780
<< : 30E7800000
>> : FFFFFFFFFFFFFD15
>>& : FD15
= : 30E780FD15
int(210042420501)
This may be more than what you are looking for, but I thought it would be fun to construct as an answer. Here is a simple format-preserving encryption which takes any 16-bit number (i.e. from 0 to 65535) and encrypts it to another 16-bit number and back again, based on a 128-bit symmetric key. You can build something like this.
It's deterministic, in that any input always encrypts to the same output with the same key, but for any number n, there is no way to predict the output for n + 1.
# Written in Ruby -- implement in PHP left as an exercise for the reader
require 'openssl'
def encrypt_block(b, k)
cipher = OpenSSL::Cipher::Cipher.new 'AES-128-ECB'
cipher.encrypt
cipher.key = k
cipher.update(b) + cipher.final
end
def round_key(i, k)
encrypt_block(i.to_s, k)
end
def prf(c, k)
encrypt_block(c.chr, k)[0].ord
end
def encrypt(m, key)
left = (m >> 8) & 0xff
right = m & 0xff
(1..7).each do |i|
copy = right
right = left ^ prf(right, round_key(i, key))
left = copy
end
(left << 8) + right
end
def decrypt(m, key)
left = (m >> 8) & 0xff
right = m & 0xff
(1..7).each do |i|
copy = left
left = right ^ prf(left, round_key(8 - i, key))
right = copy
end
(left << 8) + right
end
key = "0123456789abcdef"
# This shows no fails and no collisions
x = Hash.new
(0..65535).each do |n|
c = encrypt(n, key)
p = decrypt(c, key)
puts "FAIL" if n != p
puts "COLLISION" if x.has_key? c
x[c] = n
end
# Here are some samples
(0..10).each do |n|
c = encrypt(n, key)
p = decrypt(c, key)
puts "#{n} --> #{c}"
end
(0..10).each do
n = rand(65536)
c = encrypt(n, key)
p = decrypt(c, key)
puts "#{n} --> #{c}"
end
Some examples:
0 --> 39031
1 --> 38273
2 --> 54182
3 --> 59129
4 --> 18743
5 --> 7628
6 --> 8978
7 --> 15474
8 --> 49783
9 --> 24614
10 --> 58570
1343 --> 19234
19812 --> 18968
6711 --> 31505
42243 --> 29837
62617 --> 52334
27174 --> 56551
3624 --> 31768
38685 --> 40918
27826 --> 42109
62589 --> 25562
20377 --> 2670
a simply function that mangles integers keeping the smaller numbers small (if you need to preserve magnitude):
function switchquartets($n){
return ((0x0000000F & $n) << 4) + ((0x000000F0& $n)>>4)
+ ((0x00000F00 & $n) << 4) + ((0x0000F000& $n)>>4)
+ ((0x000F0000 & $n) << 4) + ((0x00F00000& $n)>>4)
+ ((0x0F000000 & $n) << 4) + ((0xF0000000& $n)>>4);
}
You can simply use 3DES CBC mode encryption to perform the operation. If you want to only accept values that you've generated, you can add a HMAC to the ciphertext. If the HMAC is not enough, you could rely on the format of the numbers for this particular scheme. If you want users not to be able to copy the values to each other, you can use a random IV.
So basically you store the number as a 8 byte or 8 ASCII character string by left-padding with zero values. Then you perform an encryption of a single block. This allows you to have 2^64 or 10^8 numbers. You can base 64 encrypt the result, replacing the + and / characters with the URL-safe - and _ characters.
Note that this encryption/decryption is of course bijective (or a permutation, as it is usually called in crypto). That's OK though, as the output is large enough for an attacker to have trouble guessing a value.
method "double square":
function dsCrypt($input,$decrypt=false) {
$o = $s1 = $s2 = array(); // Arrays for: Output, Square1, Square2
// формируем базовый массив с набором символов
$basea = array('?','(','#',';','$','#',"]","&",'*'); // base symbol set
$basea = array_merge($basea, range('a','z'), range('A','Z'), range(0,9) );
$basea = array_merge($basea, array('!',')','_','+','|','%','/','[','.',' ') );
$dimension=9; // of squares
for($i=0;$i<$dimension;$i++) { // create Squares
for($j=0;$j<$dimension;$j++) {
$s1[$i][$j] = $basea[$i*$dimension+$j];
$s2[$i][$j] = str_rot13($basea[($dimension*$dimension-1) - ($i*$dimension+$j)]);
}
}
unset($basea);
$m = floor(strlen($input)/2)*2; // !strlen%2
$symbl = $m==strlen($input) ? '':$input[strlen($input)-1]; // last symbol (unpaired)
$al = array();
// crypt/uncrypt pairs of symbols
for ($ii=0; $ii<$m; $ii+=2) {
$symb1 = $symbn1 = strval($input[$ii]);
$symb2 = $symbn2 = strval($input[$ii+1]);
$a1 = $a2 = array();
for($i=0;$i<$dimension;$i++) { // search symbols in Squares
for($j=0;$j<$dimension;$j++) {
if ($decrypt) {
if ($symb1===strval($s2[$i][$j]) ) $a1=array($i,$j);
if ($symb2===strval($s1[$i][$j]) ) $a2=array($i,$j);
if (!empty($symbl) && $symbl===strval($s2[$i][$j])) $al=array($i,$j);
}
else {
if ($symb1===strval($s1[$i][$j]) ) $a1=array($i,$j);
if ($symb2===strval($s2[$i][$j]) ) $a2=array($i,$j);
if (!empty($symbl) && $symbl===strval($s1[$i][$j])) $al=array($i,$j);
}
}
}
if (sizeof($a1) && sizeof($a2)) {
$symbn1 = $decrypt ? $s1[$a1[0]][$a2[1]] : $s2[$a1[0]][$a2[1]];
$symbn2 = $decrypt ? $s2[$a2[0]][$a1[1]] : $s1[$a2[0]][$a1[1]];
}
$o[] = $symbn1.$symbn2;
}
if (!empty($symbl) && sizeof($al)) // last symbol
$o[] = $decrypt ? $s1[$al[1]][$al[0]] : $s2[$al[1]][$al[0]];
return implode('',$o);
}
echo dsCrypt('586851105743');
echo '<br />'.dsCrypt('tdtevmdrsdoc', 1);

javascript translation, encode in php decode in javascript

Hi I'm trying to encode a string in PHP then output in javascript because otherwise Javascript gives me error.
I tried this http://pastebin.com/7RmjDcJY:
<?php
echo "<script type=\"text/javascript\">
function lang(translate){
var translations = new Array();";
foreach($languageTranslations AS $key=>$value):
echo "translations[\"".$key."\"] = \"". base64_encode($value)."\";";
endforeach;
echo "return (typeof translations[translate]!='undefined') ? $.base64.decode(translations[translate]) : translate;
}
</script>";?>
But förnamn -> Förnamn
Any idea? I've utf-8 in my document, but I guess bas64 can't convert utf-8 properly?
I can't just output the value, because some contains characters that breaks my javascript.
Or should I do a replace first? Like replace " with \" and stuff?
EDIT:
Now I got:
//urlencode in PHP and:
decodeURIComponent(translations[translate]).replace('+',' ')
But that doesn't feel like the right thing. What if I had an + sign in my text?
for send data from php to JavaScript you can base64 data and if you have more than one data to send use json_encode for send multi data,then in javaScript use json decode for get value and decode base64 by this code
var Base64 = {
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for encoding
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = Base64._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
}
return output;
},
// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = Base64._utf8_decode(output);
return output;
},
// private method for UTF-8 encoding
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}
sample:
alert(Base64._utf8_decode(2LTYs9uM2YTYqNi02LPbjNio2YLYq9in24zYqNmE2LDYs9uM2KjYsQ==));
this code compatible with utf-8

CRC 16 -DECT with poly x^16 + x^10 + x^8 + x^7 + x^3 + 1

believe me I have tried to code this, tried Google, and haven't had any luck.
I'm trying to implement a CRC16 using this poly
x^16 + x^10 + x^8 + x^7 + x^3 + 1
using the C language. Since I understand PHP better I'm trying to get a function going, but I'm not getting the right answer of 28713. This code is generating a CRC of 32713.
function crc16($string,$crc=0) {
for ( $x=0; $x<strlen( $string ); $x++ ) {
$crc = $crc ^ ord( $string[$x] );
echo $crc.'<br />';
for ($y = 0; $y < 8 ; $y++) {
if ( ($crc & 0x0001) == 0x0001 ) $crc = ( ($crc >> 1 ) ^ 0x10589 );
else $crc = $crc >> 1;
}
}
return $crc;
}
echo 'CRC:'.crc16('10100011');
Please I beg anyone to give a hand with this..thanks in advance.
Some CRCs are defined to process the bits from each byte from MSB to LSB, and some are defined to process bits from LSB to MSB (the latter is generally the order which is described as "reflected" and uses a reversed polynomial). Your code puts new bits in at the LSB end of the CRC and shifts right, which is suitable for a reflected CRC, but CRC-16-DECT appears to be one of the non-reflected ones.
Your input of "10100011" suggests binary, but is being processed as an 8-byte ASCII string.
To see what happens when treating 10100011 as binary instead, and working from MSB first, here's a hand calculation (as 8 bits of input doesn't require very much effort):
polynomial coefficients
|
| 10100010 <--- quotient (irrelevant)
v __________
10000010110001001 ) 10100011 <-------- input
^ 10000010110001001
-----------------
= 100001110001001
^ 10000010110001001
-----------------
= 101110101101
^ 10000010110001001
-----------------
remainder (CRC) -----> = 111000000101001
= 0x7029 = 28713
So treating the input as binary and working MSB first is the right thing to do.
Here is some C code to do the job (as I'm not really into PHP, and ultimately you want C code anyway):
#include <stdio.h>
#include <stdint.h>
static uint16_t crc16(const uint8_t *data, size_t len)
{
size_t i, j;
uint16_t crc = 0;
for (i = 0; i < len; i++) {
crc ^= (data[i] << 8); /* data at top end, not bottom */
for (j = 0; j < 8; j++) {
if ((crc & 0x8000) == 0x8000) /* top bit, not bottom */
crc = (crc << 1) ^ 0x0589; /* shift left, not right */
else
crc <<= 1; /* shift left, not right */
}
}
return crc;
}
int main(void)
{
const uint8_t in[] = { 0xa3 }; /* = 10100011 in binary */
uint16_t crc = crc16(in, sizeof(in));
printf("%u (0x%x)\n", crc, crc);
return 0;
}
Result:
$ gcc -Wall -o crc16 crc16.c
$ ./crc16
28713 (0x7029)
$
Try changing 0x10589 to 0xA001:
function crc16($string,$crc=0) {
for ( $x=0; $x<strlen( $string ); $x++ ) {
$crc = $crc ^ ord( $string[$x] );
for ($y = 0; $y < 8; $y++) {
if ( ($crc & 0x0001) == 0x0001 ) $crc = ( ($crc >> 1 ) ^ 0xA001 );
else $crc = $crc >> 1;
}
}
return $crc;
}
This code works everytime, but I'm not exactly understanding what's going on.
char *MakeCRC(char *BitString)
{
static char Res[17]; // CRC Result
char CRC[16];
int i;
char DoInvert;
for (i=0; i<16; ++i) CRC[i] = 0; // Init before calculation
for (i=0; i<strlen(BitString); ++i)
{
DoInvert = ('1'==BitString[i]) ^ CRC[15]; // XOR required?
CRC[15] = CRC[14];
CRC[14] = CRC[13];
CRC[13] = CRC[12];
CRC[12] = CRC[11];
CRC[11] = CRC[10];
CRC[10] = CRC[9] ^ DoInvert;
CRC[9] = CRC[8];
CRC[8] = CRC[7] ^ DoInvert;
CRC[7] = CRC[6] ^ DoInvert;
CRC[6] = CRC[5];
CRC[5] = CRC[4];
CRC[4] = CRC[3];
CRC[3] = CRC[2] ^ DoInvert;
CRC[2] = CRC[1];
CRC[1] = CRC[0];
CRC[0] = DoInvert;
}
for (i=0; i<16; ++i) Res[15-i] = CRC[i] ? '1' : '0'; // Convert binary to ASCII
Res[16] = 0; // Set string terminator
return(Res);
}
// A simple test driver:
#include <stdio.h>
int main()
{
char *Data, *Result; // Declare two strings
Data = "1101000101000111";
Result = MakeCRC(Data); // Calculate CRC
printf("CRC of [%s] is [%s] with P=[10000010110001001]\n", Data, Result);
return(0);
}

Generating Luhn Checksums

There are lots of implementations for validating Luhn checksums but very few for generating them. I've come across this one however in my tests it has revealed to be buggy and I don't understand the logic behind the delta variable.
I've made this function that supposedly should generated Luhn checksums but for some reason that I haven't yet understood the generated checksums are invalid half of the time.
function Luhn($number, $iterations = 1)
{
while ($iterations-- >= 1)
{
$stack = 0;
$parity = strlen($number) % 2;
$number = str_split($number, 1);
foreach ($number as $key => $value)
{
if ($key % 2 == $parity)
{
$value *= 2;
if ($value > 9)
{
$value -= 9;
}
}
$stack += $value;
}
$stack = 10 - $stack % 10;
if ($stack == 10)
{
$stack = 0;
}
$number[] = $stack;
}
return implode('', $number);
}
Some examples:
Luhn(3); // 37, invalid
Luhn(37); // 372, valid
Luhn(372); // 3728, invalid
Luhn(3728); // 37283, valid
Luhn(37283); // 372837, invalid
Luhn(372837); // 3728375, valid
I'm validating the generated checksums against this page, what am I doing wrong here?
For future reference, here is the working function.
function Luhn($number, $iterations = 1)
{
while ($iterations-- >= 1)
{
$stack = 0;
$number = str_split(strrev($number), 1);
foreach ($number as $key => $value)
{
if ($key % 2 == 0)
{
$value = array_sum(str_split($value * 2, 1));
}
$stack += $value;
}
$stack %= 10;
if ($stack != 0)
{
$stack -= 10;
}
$number = implode('', array_reverse($number)) . abs($stack);
}
return $number;
}
I dropped the $parity variable since we don't need it for this purpose, and to verify:
function Luhn_Verify($number, $iterations = 1)
{
$result = substr($number, 0, - $iterations);
if (Luhn($result, $iterations) == $number)
{
return $result;
}
return false;
}
Edit: Sorry, I realize now that you had almost my entire answer already, you had just incorrectly determined which factor to use for which digit.
My entire answer now can be summed up with this single sentence:
You have the factor reversed, you're multiplying the wrong digits by 2 depending on the length of the number.
Take a look at the Wikipedia article on the Luhn algorithm.
The reason your checksum is invalid half the time is that with your checks, half the time your number has an odd number of digits, and then you double the wrong digit.
For 37283, when counting from the right, you get this sequence of numbers:
3 * 1 = 3 3
8 * 2 = 16 --> 1 + 6 = 7
2 * 1 = 2 2
7 * 2 = 14 --> 1 + 4 = 5
+ 3 * 1 = 3 3
= 20
The algorithm requires you to sum the individual digits from the original number, and the individual digits of the product of those "every two digits from the right".
So from the right, you sum 3 + (1 + 6) + 2 + (1 + 4) + 3, which gives you 20.
If the number you end up with ends with a zero, which 20 does, the number is valid.
Now, your question hints at you wanting to know how to generate the checksum, well, that's easy, do the following:
Tack on an extra zero, so your number goes from xyxyxyxy to xyxyxyxy0
Calculate the luhn checksum sum for the new number
Take the sum, modulus 10, so you get a single digit from 0 to 10
If the digit is 0, then congratulations, your checksum digit was a zero
Otherwise, calculate 10-digit to get what you need for the last digit, instead of that zero
Example: Number is 12345
Tack on a zero: 123450
Calculate the luhn checksum for 123450, which results in
0 5 4 3 2 1
1 2 1 2 1 2 <-- factor
0 10 4 6 2 2 <-- product
0 1 0 4 6 2 2 <-- sum these to: 0+1+0+4+6+2+2=15
Take the sum (15), modulus 10, which gives you 5
Digit (5), is not zero
Calculate 10-5, which gives you 5, the last digit should be 5.
So the result is 123455.
your php is buggy, it leads into an infinite loop.
This is the working version that I'm using, modified from your code
function Luhn($number) {
$stack = 0;
$number = str_split(strrev($number));
foreach ($number as $key => $value)
{
if ($key % 2 == 0)
{
$value = array_sum(str_split($value * 2));
}
$stack += $value;
}
$stack %= 10;
if ($stack != 0)
{
$stack -= 10; $stack = abs($stack);
}
$number = implode('', array_reverse($number));
$number = $number . strval($stack);
return $number;
}
Create a php and run in your localhost Luhn(xxxxxxxx) to confirm.
BAD
I literally cannot believe how many crummy implementations there are out there.
IDAutomation has a .NET assembly with a MOD10() function to create but it just doesn't seem to work. In Reflector the code is way too long for what it's supposed to be doing anyway.
BAD
This mess of a page which is actually currently linked to from Wikipedia(!) for Javascript has several verification implementations that don't even return the same value when I call each one.
GOOD
The page linked to from Wikipedia's Luhn page has a Javascript encoder which seems to work :
// Javascript
String.prototype.luhnGet = function()
{
var luhnArr = [[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8,1,3,5,7,9]], sum = 0;
this.replace(/\D+/g,"").replace(/[\d]/g, function(c, p, o){
sum += luhnArr[ (o.length-p)&1 ][ parseInt(c,10) ]
});
return this + ((10 - sum%10)%10);
};
alert("54511187504546384725".luhnGet());​
GOOD
This very useful EE4253 page verifies the check-digit and also shows the full calculation and explanation.
GOOD
I needed C# code and ended up using this code project code:
// C#
public static int GetMod10Digit(string data)
{
int sum = 0;
bool odd = true;
for (int i = data.Length - 1; i >= 0; i--)
{
if (odd == true)
{
int tSum = Convert.ToInt32(data[i].ToString()) * 2;
if (tSum >= 10)
{
string tData = tSum.ToString();
tSum = Convert.ToInt32(tData[0].ToString()) + Convert.ToInt32(tData[1].ToString());
}
sum += tSum;
}
else
sum += Convert.ToInt32(data[i].ToString());
odd = !odd;
}
int result = (((sum / 10) + 1) * 10) - sum;
return result % 10;
}
GOOD
This validation code in C# seems to work, if a little unwieldy. I just used it to check the above was correct.
There's now a github repo based on the original question/answer. See
https://github.com/xi-project/xi-algorithm
It's also available at packagist
This is a function that could help you, it's short and it works just fine.
function isLuhnValid($number)
{
if (empty($number))
return false;
$_j = 0;
$_base = str_split($number);
$_sum = array_pop($_base);
while (($_actual = array_pop($_base)) !== null) {
if ($_j % 2 == 0) {
$_actual *= 2;
if ($_actual > 9)
$_actual -= 9;
}
$_j++;
$_sum += $_actual;
}
return $_sum % 10 === 0;
}
Since the other answers that displayed or linked to C# weren't working, I've added a tested and more explanatory C# version:
/// <summary>
/// Calculates Luhn Check Digit based on
/// https://en.wikipedia.org/wiki/Luhn_algorithm
/// </summary>
/// <param name="digits">The digits EXCLUDING the check digit on the end.
/// The check digit should be compared against the result of this method.
/// </param>
/// <returns>The correct checkDigit</returns>
public static int CalculateLuhnCheckDigit(int[] digits)
{
int sum = 0;
bool isMultiplyByTwo = false;
//Start the summing going right to left
for (int index = digits.Length-1; index >= 0; --index)
{
int digit = digits[index];
//Every other digit should be multipled by two.
if (isMultiplyByTwo)
digit *= 2;
//When the digit becomes 2 digits (due to digit*2),
//we add the two digits together.
if (digit > 9)
digit = digit.ToString()
.Sum(character => (int)char.GetNumericValue(character));
sum += digit;
isMultiplyByTwo = !isMultiplyByTwo;
}
int remainder = sum % 10;
//If theres no remainder, the checkDigit is 0.
int checkDigit = 0;
//Otherwise, the checkDigit is the number that gets to the next 10
if (remainder != 0)
checkDigit = 10 - (sum % 10);
return checkDigit;
}
An example of its use:
public static bool IsValid(string userValue)
{
//Get the check digit from the end of the value
int checkDigit = (int)char.GetNumericValue(userValue[userValue.Length - 1]);
//Remove the checkDigit for the luhn calculation
userValue = userValue.Substring(0, userValue.Length - 1);
int[] userValueDigits = userValue.Select(ch => (int)char.GetNumericValue(ch))
.ToArray();
int originalLuhnDigit = CalculateLuhnCheckDigit(userValueDigits);
//If the user entered check digit matches the calcuated one,
//the number is valid.
return checkDigit == originalLuhnDigit;
}
The parity check must start from the right.
Try this:
<?php
function Luhn($digits) {
$sum = 0;
foreach (str_split(strrev($digits)) as $i => $digit) {
$sum += ($i % 2 == 0) ? array_sum(str_split($digit * 2)) : $digit;
}
return $digits . (10 - ($sum % 10)) % 10;
}
Add Luhn checksum to $input
$digits = Luhn($input);
Verify a number with Luhn checksum in it:
if ($digits == Luhn(substr($digits, 0, -1))) {
// ...
}
Get the checksum number:
$luhn_digit = substr(Luhn($digits), -1);
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int *LONT, n, TARF;
int SEGVT = 0;
int SEGVT2 = 0;
string TARJETA;
double VA;
cout << "cuantos digitos tiene la tarjeta: " << endl;
cin >> n;
LONT = new int[n];
do {
cout << "ingrese el # de la tarjeta: " << endl;
cin >> TARJETA;
VA = stod(TARJETA);
} while (VA < 0);
for (int POS = 0; POS < TARJETA.size(); POS++) {
LONT[POS] = TARJETA[POS] - '0';
}
for (int i = 0; i < n; i++) {
if (i % 2 == 0) {
LONT[i] = TARJETA[i] - '0';
LONT[i] = LONT[i] * 2;
if (LONT[i] >= 10) {
LONT[i] = LONT[i] - 9;
}
SEGVT2 = SEGVT2 + LONT[i];
}
else
{
LONT[i] = TARJETA[i] - '0';
SEGVT = SEGVT + LONT[i];
}
}
TARF = SEGVT + SEGVT2;
if (TARF % 10 == 0) {
cout << SEGVT2 << SEGVT;
cout << "El numero de tarjeta " << TARJETA << "; Es de una tarjeta valida (YA QUE SU MOD10 ES " << TARF << endl;
}
else
{
cout << SEGVT2 << SEGVT;
cout << "El numero de tarjeta" << TARJETA << "; No es de una tarjeta valida (YA QUE SU MOD10 ES " << TARF << endl;
}
delete[] LONT;
}

Categories