Related
I need the default behaviour (i.e ENT_COMPAT | ENT_HTML401) of the PHP-function htmlspecialchars() in C, how is this done best (that means fastest) in C?
I don't need the input string, therefore an in-place solution is possible.
It is a really simple function, it just converts these characters:
'&' -> '&'
'"' -> '"'
'<' -> '<'
'>' -> '>'
What strategy would be fastest? Looping over each character individually and creating the output buffer byte-for-byte, overwriting the input string in-place or some other solution?
This code assumes that input and output are buffers and that input contains the input string. It also assumes that the output buffer is large enough to hold the output (if not output is truncated):
long i = 0;
long j = 0;
while (input[i])
{
if (input[i] == '<')
{
memcpy(&output[j], "<", 4);
j += 4;
} else if (input[i] == '>')
{
memcpy(&output[j], ">", 4);
j += 4;
} else if (input[i] == '"')
{
memcpy(&output[j], """, 6);
j += 6;
} else if (input[i] == '&')
{
memcpy(&output[j], "&", 5);
j += 5;
} else
{
output[j++] = input[i];
}
if (j > sizeof(output)-7)
{
break;
}
i++;
}
output[j] = 0;
In C, ugly code is often the fastest.
An in-place solution would only yield performance benefits if the characters to be exchanged would be very, very rare so that the whole string can be reordered (very expensive) on every character that is detected. With normal HTML-data, where these 4 characters will appear often, an in-place solution would be much slower.
You can build a solution that works in both cases:
Calculates the required space and return an allocated string when NULL is passed, otherwise fill the passed string:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static size_t encode_len(const char *str)
{
size_t len = 0;
while (*str) {
if (*str == '"' || *str == '&' || *str == '<' || *str == '>') {
len += 5;
} else {
len += 1;
}
str++;
}
return len;
}
static char *encode(const char *str, char *dest)
{
char *ptr;
if (dest == NULL) {
dest = malloc(encode_len(str) + 1);
if (dest == NULL) return NULL;
}
ptr = dest;
while (*str) {
switch (*str) {
case '"': memcpy(ptr, """, 5); ptr += 5; break;
case '&': memcpy(ptr, "&", 5); ptr += 5; break;
case '<': memcpy(ptr, "<", 5); ptr += 5; break;
case '>': memcpy(ptr, ">", 5); ptr += 5; break;
default: *ptr++ = *str;
}
str++;
}
*ptr = *str;
return dest;
}
int main(void)
{
/* Returns an allocated string */
char *str = encode("testing & <> \"", NULL);
if (str) {
printf("%s\n", str);
free(str);
}
/* Fills a passed string */
char str2[128];
encode("testing & <> \"", str2);
printf("%s\n", str2);
return 0;
}
Here is htmlspecialchars function safe implementation.
Info
char *_output is the result.
size_t outlen is the maximum number of bytes allowed to write to _output.
char *_input is the string to be HTML escaped.
size_t inlen is the length of string to be escaped (excluding null terminator).
This function returns the number of bytes written to _output, including null terminator.
Note: This function always puts null terminator to the _output.
Code
#include <stdio.h>
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include <stdint.h>
#define likely(EXPR) __builtin_expect(!!(EXPR), 1)
#define unlikely(EXPR) __builtin_expect(!!(EXPR), 0)
/*
* `char *_output` is the result.
*
* `size_t outlen` is the maximum number of bytes allowed to write to `_output`.
*
* `char *_input` is the string to be HTML escaped.
*
* `size_t inlen` is the length of string to be escaped (excluding null
* terminator).
*
* This function returns the number of bytes written to `_output`, including
* null terminator.
*
* Note: This function always puts null terminator to the `_output`.
*
*/
size_t htmlspecialchars(char * restrict _output, size_t outlen,
const char * restrict _input, size_t inlen)
{
struct html_char_map {
const char to[8];
const uint8_t len;
};
static const struct html_char_map html_map[0xffu] = {
['<'] = {"<", 4},
['>'] = {">", 4},
['"'] = {""", 6},
['&'] = {"&", 5},
};
size_t j = 0;
uint8_t len = 0;
unsigned char * restrict output = (unsigned char *)_output;
const unsigned char * restrict input = (const unsigned char *)_input;
const unsigned char *in_end = input + inlen;
while (likely(input < in_end)) {
const unsigned char *cp;
const struct html_char_map *map_to = &html_map[(size_t)*input];
if (*map_to->to == '\0') {
cp = input;
len = 1;
} else {
cp = (const unsigned char *)map_to->to;
len = map_to->len;
}
if (unlikely((j + len - 1) >= outlen))
break;
memcpy(&output[j], cp, len);
j += len;
input++;
}
if (likely(outlen > 0)) {
if (unlikely((j + 1) > outlen))
j -= len;
output[++j] = '\0';
}
return j;
}
int main(void)
{
size_t len;
char output[0xff];
const char input[] = "Google<<>>";
const char expected_output[] = "<a href="https://www.google.com">Google</a><<>>";
/* Input length (without null terminator) */
size_t input_len = sizeof(input) - 1;
/* Max allowed write bytes */
size_t output_size = sizeof(output);
len = htmlspecialchars(output, output_size, input, input_len);
/* `len` includes null terminator char */
printf("Written bytes to output: %zu\n", len);
/* `output` */
printf("output = %s\n", output);
assert(!memcmp(output, expected_output, sizeof(expected_output)));
}
I'm trying to make a mildly secure communication between Arduino and PHP. I can not use SSL for lack of power on the Arduino. So I wanted to use RC4 to encrypt data from PHP, and receive into the Arduino and decrypt. also encrypt from the Arduino and send to PHP.
The problem is that the encrypted data sent from PHP, do not coincide in the Arduino.
On PHP I get HesshwkfFk8Q in base64 and in the Arduino i get nZcwrlpZEr0V in base64.
different results when they should be equal.
I think I have a wrong Arduino RC4 implementation. I'm using this https://github.com/adamvr/arduino-base64
This is the code:
Arduino
#include <Base64.h>
unsigned char S[256];
char has[512];
#define S_SWAP(a,b) do { int t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
void rc4(char *key, char *data){
int i,j;
for (i=0;i<256;i++){
S[i] = i;
}
j = 0;
for (i=0;i<256;i++){
j = (j+S[i]+key[i%strlen(key)]) %256;
S_SWAP(S[i],S[j]);
}
i = j = 0;
for (int k=0;k<strlen(data);k++){
i = (i+1) %256;
j = (j+S[i]) %256;
S_SWAP(S[i],S[j]);
has[k] = data[k]^S[(S[i]+S[j]) %256];
}
has[strlen(data)+1] = '\0';
}
void setup() {
Serial.begin(9600);
char key[] = "Hello";
char sdata[] = "secretMsg";
rc4(key,sdata);
Serial.print("Encrypted : ");
char out[100];
base64_encode(out,has,strlen(has));
Serial.println(out);
char out2[100];
base64_decode(out2,out,strlen(out));
rc4(key,out2);
Serial.print("Decrypted : ");
Serial.println(has);
}
void loop(){
}
PHP
<?php
$key = 'Hello';
$msg = 'secretMsg';
$encrypted = rc4_crypt($key, $msg);
echo 'encrypted b64: ', base64_encode($encrypted) ,'<br>';
echo "decrip: " , rc4_decrypt($key,rc4_crypt($key, $msg));
exit;
function rc4_crypt($key,$msg) {
$td = mcrypt_module_open('arcfour', '' , 'stream', '');
mcrypt_generic_init($td, $key, null);
$encrypted = mcrypt_generic($td, $msg);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $encrypted;
}
function rc4_decrypt($key,$msg) {
return rc4_crypt($key,$msg);
}
?>
I had the same problem and I can confirm you that your RC4 function in Arduino is wrong, you can use this instead:
unsigned char S[256];
unsigned int i, j;
void swap(unsigned char *s, unsigned int i, unsigned int j) {
unsigned char temp = s[i];
s[i] = s[j];
s[j] = temp;
}
/* KSA */
void rc4_init(unsigned char *key, unsigned int key_length) {
for (i = 0; i < 256; i++)
S[i] = i;
for (i = j = 0; i < 256; i++) {
j = (j + key[i % key_length] + S[i]) & 255;
swap(S, i, j);
}
i = j = 0;
}
/* PRGA */
unsigned char rc4_output() {
i = (i + 1) & 255;
j = (j + S[i]) & 255;
swap(S, i, j);
return S[(S[i] + S[j]) & 255];
}
This is the current implementation that i'm using
#define SWAP(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
class RC4
{
public:
RC4 ()
{
memset(sbox,0,256);
memset(key,0,256);
}
virtual ~RC4 ()
{
memset(sbox,0,256);
memset(key,0,256);
}
char *Encrypt(char *pszText,const char *pszKey)
{
i=0, j=0,n = 0;
ilen = (int)strlen(pszKey);
for (m = 0; m < 256; m++)
{
*(key + m)= *(pszKey + (m % ilen));
*(sbox + m) = m;
}
for (m=0; m < 256; m++)
{
n = (n + *(sbox+m) + *(key + m)) &0xff;
SWAP(*(sbox + m),*(sbox + n));
}
ilen = (int)strlen(pszText);
for (m = 0; m < ilen; m++)
{
i = (i + 1) &0xff;
j = (j + *(sbox + i)) &0xff;
SWAP(*(sbox+i),*(sbox + j));
k = *(sbox + ((*(sbox + i) + *(sbox + j)) &0xff ));
if(k == *(pszText + m))
k = 0;
*(pszText + m) ^= k;
}
return pszText;
}
char *Decrypt(char *pszText,const char *pszKey)
{
return Encrypt(pszText,pszKey) ;
}
private:
unsigned char sbox[256];
unsigned char key[256],k;
int m, n, i, j, ilen;
};
;
After a lot of trials without success I ended up with the following three codes:
Arduino code implemented RC4 (adapted from this C code) and encoding the encrypted result in Base64
PHP code that decodes base64 and decrypts RC4
HTML to test the PHP (and eventually it will be the index of ESP32 Webserver). ATTENTION! sending Base64 in the Url can be dangerous becasue the characters '+' '/' '=' can create problems, so make sure you read this post Base64 in url and the charachters that can be problematic are replaced by '.' '_' '-'
At time of writing I am using Arduino core for ESP32 version 2.0.0 consider that if you are not using this version of Base64.h there could be incompatibility (more details here)
Arduino Code
#include <stdio.h>
#include <string.h>
#include "base64.h"
typedef unsigned long ULONG;
void rc4_init(unsigned char *s, unsigned char *key, unsigned long Len)
{
int i =0, j = 0;
char k[256] = {0};
unsigned char tmp = 0;
for (i=0;i<256;i++) {
s[i] = i;
k[i] = key[i%Len];
}
for (i=0; i<256; i++) {
j=(j+s[i]+k[i])%256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
void rc4_crypt(unsigned char *s, unsigned char *Data, unsigned long Len)
{
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for(k=0;k<Len;k++) {
i=(i+1)%256;
j=(j+s[i])%256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t=(s[i]+s[j])%256;
Data[k] ^= s[t];
}
}
int main()
{
unsigned char s[256] = {0}; //S-box
char key[256] = "Hello";
char pData[512] = "secretMsg";
ULONG len = strlen(pData);
printf("key : %s\n", key);
printf("raw : %s\n", pData);
rc4_init(s,(unsigned char *)key,strlen(key));
rc4_crypt(s,(unsigned char *)pData,len);
printf("encrypt : %s\n", pData);
base64 b;
String encoded = b.encode((unsigned char *)pData, strlen(pData));
Serial.println(encoded);
rc4_init(s,(unsigned char *)key, strlen(key));
rc4_crypt(s,(unsigned char *)pData,len);
printf("decrypt : %s\n",pData);
return 0;
}
void setup(){
Serial.begin(115200);
main();
}
void loop(){
}
PHP CODE
<?php
function rc4_crypt($key,$msg) {
$td = mcrypt_module_open('arcfour', '' , 'stream', '');
mcrypt_generic_init($td, $key, null);
$encrypted = mcrypt_generic($td, $msg);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $encrypted;
}
function rc4_decrypt($key,$msg) {
return rc4_crypt($key,$msg);
}
if(isset($_POST['base'])) {
$key = 'Hello';
$msg_revealed = $_POST['base'];
rc4_decrypt($key, base64_decode($msg_revealed)) //decode form base64 and decrypt
$msg = 'secretMsg'; //for testing
$encrypted = rc4_crypt($key, $msg);
echo 'encrypted b64: ', base64_encode($encrypted) ,'<br>';
echo "decrip: " , rc4_decrypt($key,rc4_crypt($key, $msg));
exit;
}
?>
HTML CODE FOR TESTING and eventually the code that will be hosted on ESP32 webserver (more info here)
<html >
<head>
<title>test Base64</title>
<meta http-equiv='content-type' content='text/html;charset=utf-8' />
<meta name='generator' content='Geany 1.36' />
</head>
<body>
<form action='https://www.yourwebsite.com/base64.php' method='post' id='downloadForm'>
<input hidden name='base' value='PASS_THE_URL_BASE64_ENCRYPTED_STRING_HERE'>
</form>
<div style='text-align: center;'><button type='button' class='btn btn-danger' onclick='sendBaseForm()'>TEST</button></div>
</body>
<script>
function sendBaseForm(){
document.getElementById('downloadForm').submit();
}
</script>
</html>
What is a simple, elegant way to list the first x number of IPv6 IPs from a IPv6 string.
For example,
listIPs("2600:f333:10:c000::0", 4)
echos
2600:f333:10:c000::1
2600:f333:10:c000::2
2600:f333:10:c000::3
2600:f333:10:c000::4
Here's a sample of code that may have worked for IPv4, as it converted to int:
$input = "2600:f333:10:c000::/51";
$max = 4;
list($block, $cidr) = explode("/", $input);
$first = inet_pton( $block );
echo inet_ntop($first) . "\n";
for ($i = 1; $i < $max; $i++) {
//todo: die if it has exceeded block size based on $cidr
echo inet_ntop($first + $i) . "\n"; //doesn't work, packed binary?
}
Here's an example program written in C (since I don't know C++). It's fairly fast, but I'm not really happy with it. Maybe someone can help me improve it.
Edit: Obviously, I wrote this before it was turned into a PHP-only question. Turning this into PHP is left as an exercise to the reader (ew).
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
/*
* Syntax: ./ipv6_list <ip>/<cidr-prefix>
*/
int main(int argc, char **argv) {
uint8_t start[16];
uint8_t address[16];
uint8_t mask[16] = { 0 };
uint8_t prefix = 128;
char *prefix_location;
int i;
/* This is the octet that, when changed, will result in <IP> & <mask> != <start IP> */
int mask_check_octet = 0;
if(argc != 2)
return 1;
/* Find prefix */
if((prefix_location = strstr(argv[1], "/")) != NULL) {
char *prefix_search = prefix_location + 1;
char *prefix_remaining;
long prefix_test;
if(!isdigit(*prefix_search))
return 2;
errno = 0;
prefix_test = strtol(prefix_search, &prefix_remaining, 10);
if(errno == ERANGE || prefix_test < 0 || prefix_test > 128 || strcmp(prefix_remaining, "") != 0)
return 2;
prefix = (uint8_t)prefix_test;
*prefix_location = '\0'; /* So we can just pass argv[1] into inet_pton(3) */
}
/* Convert prefix into mask */
for(i = 0; i < 16; i++) {
if(prefix == 0)
break;
mask_check_octet = i;
if(prefix < 8) {
mask[i] = ~((1 << (8 - prefix)) - 1);
break;
}
else
mask[i] = UINT8_MAX;
prefix -= 8;
}
/* Find address */
if(inet_pton(AF_INET6, argv[1], start) != 1)
return 3;
/* Start at the beginning of the network */
for(i = 0; i < 16; i++) {
start[i] &= mask[i];
address[i] = start[i];
}
/* Iterate */
while((address[mask_check_octet] & mask[mask_check_octet]) == start[mask_check_octet]) {
char address_str[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, address, address_str, sizeof(address_str));
printf("%s\n", address_str);
/* Add one to the address */
for(i = 15; i >= 0; i--) {
if(address[i] != UINT8_MAX)
break;
}
address[i]++;
for(i++; i < 16; i++)
address[i] = 0;
};
return 0;
}
You can use standard shell commands to limit its output (or just modify the while loop):
nfontes#brioche:~$ ./ipv6_list '2607:fc50:0:d00::0/106' | head -n 200
2607:fc50:0:d00::
2607:fc50:0:d00::1
2607:fc50:0:d00::2
2607:fc50:0:d00::3
2607:fc50:0:d00::4
2607:fc50:0:d00::5
2607:fc50:0:d00::6
2607:fc50:0:d00::7
2607:fc50:0:d00::8
2607:fc50:0:d00::9
2607:fc50:0:d00::a
2607:fc50:0:d00::b
2607:fc50:0:d00::c
2607:fc50:0:d00::d
2607:fc50:0:d00::e
[...]
2607:fc50:0:d00::c0
2607:fc50:0:d00::c1
2607:fc50:0:d00::c2
2607:fc50:0:d00::c3
2607:fc50:0:d00::c4
2607:fc50:0:d00::c5
2607:fc50:0:d00::c6
2607:fc50:0:d00::c7
Something similar (in PHP). It takes an IPv4/IPv6 address and increments it by given value:
// Takes an IPv4/IPv6 address in string format, and increments it by given value
function incrementIp($ip, $increment)
{
$addr = inet_pton ( $ip );
for ( $i = strlen ( $addr ) - 1; $increment > 0 && $i >= 0; --$i )
{
$val = ord($addr[$i]) + $increment;
$increment = $val / 256;
$addr[$i] = chr($val % 256);
}
return inet_ntop ( $addr );
}
I have a Visual Basic function and I am not that familiar with VB. I need to convert it to PHP and have made a start. There are a couple of functions I'm not sure how to replicate and am looking for some help with this and to see if I have got the nesting right etc. In the following code, there is the vb function and then my attempt at te php version. it is not complete and in the php version I have commented out the vb parts I am not sure about. Can anyone help put me on the right lines?
Public Function gfnCrypt(ByVal Expression As String, ByVal Password As String) As String
'RC4 Encryption
Dim rb(0 To 255) As Integer, X As Long, Y As Long, Z As Long, Key() As Byte, ByteArray() As Byte, temp As Byte
On Error Resume Next
If Len(Password) = 0 Then
Exit Function
End If
If Len(Expression) = 0 Then
Exit Function
End If
If Len(Password) > 256 Then
Key() = StrConv(Left$(Password, 256), vbFromUnicode)
Else
Key() = StrConv(Password, vbFromUnicode)
End If
For X = 0 To 255
rb(X) = X
Next X
X = 0
Y = 0
Z = 0
For X = 0 To 255
Y = (Y + rb(X) + Key(X Mod Len(Password))) Mod 256
temp = rb(X)
rb(X) = rb(Y)
rb(Y) = temp
Next X
X = 0
Y = 0
Z = 0
ByteArray() = StrConv(Expression, vbFromUnicode)
For X = 0 To Len(Expression)
Y = (Y + 1) Mod 256
Z = (Z + rb(Y)) Mod 256
temp = rb(Y)
rb(Y) = rb(Z)
rb(Z) = temp
ByteArray(X) = ByteArray(X) Xor (rb((rb(Y) + rb(Z)) Mod 256))
Next X
gfnCrypt = StrConv(ByteArray, vbUnicode)
End Function
And in PHP:
function gfnCrypt($mywebpassword, $mywebkey) {
//'RC4 Encryption
//Dim rb(0 To 255) As Integer, X As Long, Y As Long, Z As Long, Key() As Byte, ByteArray() As Byte, temp As Byte
if(strlen($mywebpassword) == 0){
return false;
}
if(strlen($mywebkey) == 0){
return false;
}
if(strlen($mywebpassword) > 256){
//Key() = StrConv(Left$(Password, 256), vbFromUnicode)
}else{
//Key() = StrConv(Password, vbFromUnicode)
}
$rb=array();
for($x=0;$x=255;$x++){
$rb['x'] = $x;
for($x=0;$x=255;$x++){
$y = ($y + $rb['x'];// + Key(X Mod Len(Password))) Mod 256
$temp = $rb['x'];
$rb['x'] = $rb[$y];
$rb[$y] = $temp;
//ByteArray() = StrConv(Expression, vbFromUnicode)
for($x=0;$x=strlen($mywebpassword), $x++){
$y = ($y + 1);// Mod 256
$z = ($z + $rb[$y]);// Mod 256
$temp = $rb[$y];
$rb[$y] = $rb[$z];
$rb[$z] = $temp;
//ByteArray(X) = ByteArray(X) Xor (rb((rb(Y) + rb(Z)) Mod 256))
}
}
}
//gfnCrypt = StrConv(ByteArray, vbUnicode)
return $gfnCrypt;
}
The arithmetic modulo can be used in php using % operator.
$modulus = $a % $b
I think you will get errors with your 3 embedded for (x…) loops by the way.
To access an element of the array (the $ith for instance) don't use $array['i'] but $array[$i].
The StrConv must be a ut8_encode and the left stuff can be done with substr($string, 0, 255).
References: utf8_encode substr
If you are trying to do RC4 encryption in PHP then you may wan't to take a look at the project at this link http://code.google.com/p/rc4crypt/
I really hope you have some unit tests to test that:
function gfnCrypt($mywebpassword, $mywebkey) {
//'RC4 Encryption
//Dim rb(0 To 255) As Integer, X As Long, Y As Long, Z As Long, Key() As Byte, ByteArray() As Byte, temp As Byte
rb = array();
Key = array();
ByteArray = array();
if(strlen($mywebpassword) == 0){
return false;
}
if(strlen($mywebkey) == 0){
return false;
}
if(strlen($mywebpassword) > 256){
//Key() = StrConv(Left$(Password, 256), vbFromUnicode)
Key[] = ut8_encodesubstr(Password, 0, 256));
}else{
//Key() = StrConv(Password, vbFromUnicode)
Key[] = ut8_encode(Password);
}
$rb=array();
for($x=0;$x=255;$x++){
$rb['x'] = $x;
for($x=0;$x=255;$x++){
$y = ($y + $rb['x'] + Key(X % strlen(Password))) % 256;
$temp = $rb['x'];
$rb['x'] = $rb[$y];
$rb[$y] = $temp;
//ByteArray() = StrConv(Expression, vbFromUnicode)
ByteArray[] = ut8_encode(Expression);
for($x=0;$x=strlen($mywebpassword), $x++){
$y = ($y + 1);// Mod 256
$z = ($z + $rb[$y]);// Mod 256
$temp = $rb[$y];
$rb[$y] = $rb[$z];
$rb[$z] = $temp;
//ByteArray(X) = ByteArray(X) Xor (rb((rb(Y) + rb(Z)) Mod 256))
ByteArray[X] = (ByteArray[X] ^= (rb[(rb[Y] + rb[Z]] % 256)]);
}
}
}
//gfnCrypt = StrConv(ByteArray, vbUnicode)
gfnCrypt = ut8_encode(ByteArray);
return $gfnCrypt;
}
I finished the code you started, but it seems really wrong (for example, why nest 3 for loops, using the same variable ?). It doesn't even seem to match the initial VB code...
Using md5() function in PHP directly gives me the String. What I want to do before saving the string in the database is remove zeroes 0 if any in the byte representation of that hex and that byte representation is < 0x10 and then save the string in the database.
How can I do this in PHP?
MD5 - PHP - Raw Value - catch12 - 214423105677f2375487b4c6880c12ae - This is what I get now. Below is the value that I want the PHP to save in the database.
MD5 - Raw Value - catch12 - 214423105677f2375487b4c688c12ae
Wondering why? The MD5 code I have in my Android App for Login and Signup I did not append zeroes for the condition if ((b & 0xFF) < 0x10) hex.append("0"); Works fine. But the Forgot Password functionality in the site is PHP which is when the mismatch happens if the user resets password. JAVA code below.
byte raw[] = md.digest();
StringBuffer hexString = new StringBuffer();
for (int i=0; i<raw.length; i++)
hexString.append(Integer.toHexString(0xFF & raw[i]));
v_password = hexString.toString();
Any help on the PHP side so that the mismatch does not happen would be very very helpful. I can't change the App code because that would create problems for existing users.
Thank you.
Pass the "normal" MD5 hash to this function. It will parse it into the individual byte pairs and strip leading zeros.
EDIT: Fixed a typo
function convertMD5($md5)
{
$bytearr = str_split($md5, 2);
$ret = '';
foreach ($bytearr as $byte)
$ret .= ($byte[0] == '0') ? str_replace('0', '', $byte) : $byte;
return $ret;
}
Alternatively, if you don't want zero-bytes completely stripped (if you want 0x00 to be '0'), use this version:
function convertMD5($md5)
{
$bytearr = str_split($md5, 2);
$ret = '';
foreach ($bytearr as $byte)
$ret .= ($byte[0] == '0') ? $byte[1] : $byte;
return $ret;
}
$md5 = md5('catch12');
$new_md5 = '';
for ($i = 0; $i < 32; $i += 2)
{
if ($md5[$i] != '0') $new_md5 .= $md5[$i];
$new_md5 .= $md5[$i+1];
}
echo $new_md5;
To strip leading zeros (00->0, 0a->a, 10->10)
function stripZeros($md5hex) {
$res =''; $t = str_split($md5hex, 2);
foreach($t as $pair) $res .= dechex(hexdec($pair));
return $res;
}
To strip leading zeros & zero bytes (00->nothing, 0a->a, 10->10)
function stripZeros($md5hex) {
$res =''; $t = str_split($md5hex, 2);
foreach($t as $pair) {
$b = dechex(hexdec($pair));
if ($b!=0) $res .= $b;
}
return $res;
}