Skip to content

Instantly share code, notes, and snippets.

@simonwistow
Created May 3, 2023 18:07
Show Gist options
  • Save simonwistow/1ee46b419266315de70bbd0bfd229f62 to your computer and use it in GitHub Desktop.
Save simonwistow/1ee46b419266315de70bbd0bfd229f62 to your computer and use it in GitHub Desktop.
Implementations of MD5 and SHA1 in WMLS (WAP Markup Language Script) all carefully constructed to keep them under the size of 1 UDP packet for max compatibility
/*
* A WML Script implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Copyright (C) Simon Wistow, 2001
*/
use url md5aux "md5_aux.wmlsc";
function calcMD5(str)
{
var x = md5aux#str2blks_MD5(str);
var a = 0x67452301;
var b = 0xEFCDAB89;
var c = 0x98BADCFE;
var d = 0x10325476;
for(var i = 0; i < String.elements(x, '|'); i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var abcd = a + '|' + b + '|' + c + '|' + d;
abcd = md5aux#ff_four(abcd, x, i, 0, 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE);
abcd = md5aux#ff_four(abcd, x, i, 4, 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501);
abcd = md5aux#ff_four(abcd, x, i, 8, 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE);
abcd = md5aux#ff_four(abcd, x, i, 12, 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821);
abcd = md5aux#gg_four(abcd, x, i, 1, 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA);
abcd = md5aux#gg_four(abcd, x, i, 5, 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8);
abcd = md5aux#gg_four(abcd, x, i, 9, 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED);
abcd = md5aux#gg_four(abcd, x, i, 13, 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A);
abcd = md5aux#hh_four(abcd, x, i, 5, 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C);
abcd = md5aux#hh_four(abcd, x, i, 1, 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70);
abcd = md5aux#hh_four(abcd, x, i, 13, 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05);
abcd = md5aux#hh_four(abcd, x, i, 9, 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665);
abcd = md5aux#ii_four(abcd, x, i, 0, 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039);
abcd = md5aux#ii_four(abcd, x, i, 12, 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1);
abcd = md5aux#ii_four(abcd, x, i, 8, 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1);
abcd = md5aux#ii_four(abcd, x, i, 4, 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391);
a = md5aux#add( md5aux#elt(abcd, 0), olda);
b = md5aux#add( md5aux#elt(abcd, 1), oldb);
c = md5aux#add( md5aux#elt(abcd, 2), oldc);
d = md5aux#add( md5aux#elt(abcd, 3), oldd);
}
return md5aux#rhex(a) + md5aux#rhex(b) + md5aux#rhex(c) + md5aux#rhex(d);
}
extern function hash (var_to_set, string)
{
WMLBrowser.setVar(var_to_set, calcMD5(URL.unescapeString(string)));
WMLBrowser.refresh ();
}
/*
* A WML Script implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Copyright (C) Simon Wistow, 2001
*
* Auxillary functions - split into seperate files to keep each compiled
* script down below the size of one UDP packet so all phones can use it
*/
use url ordlib "ord.wmlsc";
/*
* Extract a value from one of our arrays. These are strings separated by the '|' character.
*/
extern function elt(str, index)
{
return String.elementAt (str, index, '|');
}
/*
* Extract a value from an array at offset:
* base + ((group + offset) & 0xF)
*/
extern function elt2(str, base, group, offset)
{
return elt(str, base + ((group + offset) & 0xF));
}
/*
* Reduce size by turning this into a function.
*/
extern function combine (a, b, c, d)
{
return a + "|" + b + "|" + c + "|" + d;
}
/*
* Take a string and return the hex representation of its MD5.
*/
extern function rhex(num)
{
var hex_chr = "0123456789abcdef";
var str = "";
for(var j = 0; j <= 3; j++)
str += String.charAt(hex_chr, (num >> (j * 8 + 4)) & 0x0F) +
String.charAt(hex_chr, (num >> (j * 8)) & 0x0F);
return str;
}
/*
* Convert a string to a sequence of 16-word blocks, stored as an array.
* Append padding bits and the length, as described in the MD5 standard.
*/
extern function str2blks_MD5(str)
{
var nblk = ((String.length(str) + 8) >> 6) + 1;
var blks = "0";
for(var i = 1; i < (nblk * 16); i++)
blks += '|0';
for(i = 0; i <= String.length(str); i++)
{
var temp = String.elementAt(blks, i>>2, '|');
var ord_str = ordlib#ord_string(str);
if (i != String.length(str))
temp |= String.elementAt(ord_str,i, '|') << ((i % 4) * 8);
else
temp |= 0x80 << ((i % 4) * 8);
blks = String.replaceAt(blks, temp, i>>2, '|');
}
blks = String.replaceAt(blks, String.length(str) * 8, nblk * 16 - 2, '|');
return blks;
}
/*
* Add integers, wrapping at 2^32
*/
extern function add(x, y)
{
return ((x&0x7FFFFFFF) + (y&0x7FFFFFFF)) ^ (x&0x80000000) ^ (y&0x80000000);
}
/*
* Bitwise rotate a 32-bit number to the left
*/
extern function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* These functions implement the basic operation for each round of the
* algorithm.
*/
extern function cmn(q, a, b, x, s, t)
{
return add(rol(add(add(a, q), add(x, t)), s), b);
}
extern function ff(a, b, c, d, x, s, t)
{
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
extern function gg(a, b, c, d, x, s, t)
{
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
extern function hh(a, b, c, d, x, s, t)
{
return cmn(b ^ c ^ d, a, b, x, s, t);
}
extern function ii(a, b, c, d, x, s, t)
{
return cmn(c ^ (b | (~d)), a, b, x, s, t);
}
extern function ff_four (abcd, x, i, offset, t1, t2, t3, t4)
{
var a = String.elementAt(abcd, 0, '|');
var b = String.elementAt(abcd, 1, '|');
var c = String.elementAt(abcd, 2, '|');
var d = String.elementAt(abcd, 3, '|');
i+=offset;
a = ff(a, b, c, d, String.elementAt(x, i+ 0, '|'), 7, t1);
d = ff(d, a, b, c, String.elementAt(x, i+ 1, '|'),12, t2);
c = ff(c, d, a, b, String.elementAt(x, i+ 2, '|'),17, t3);
b = ff(b, c, d, a, String.elementAt(x, i+ 3, '|'),22, t4);
return a + '|' + b + '|' + c + '|' + d;
}
extern function gg_four (abcd, x, i, offset, t1, t2, t3, t4)
{
var a = elt(abcd, 0);
var b = elt(abcd, 1);
var c = elt(abcd, 2);
var d = elt(abcd, 3);
a = gg(a, b, c, d, elt2(x, i, offset, 0), 5, t1);
d = gg(d, a, b, c, elt2(x, i, offset, 5), 9, t2);
c = gg(c, d, a, b, elt2(x, i, offset, 10), 14, t3);
b = gg(b, c, d, a, elt2(x, i, offset, 15), 20, t4);
return combine (a, b, c, d);
}
/*
* Do four hh calculations at once.
*/
extern function hh_four (abcd, x, i, offset, t1, t2, t3, t4)
{
var a = elt(abcd, 0);
var b = elt(abcd, 1);
var c = elt(abcd, 2);
var d = elt(abcd, 3);
a = hh(a, b, c, d, elt2(x, i, offset, 0), 4, t1);
d = hh(d, a, b, c, elt2(x, i, offset, 3), 11, t2);
c = hh(c, d, a, b, elt2(x, i, offset, 6), 16, t3);
b = hh(b, c, d, a, elt2(x, i, offset, 9), 23, t4);
return combine (a, b, c, d);
}
/*
* Do four ii calculations at once.
*/
extern function ii_four (abcd, x, i, offset, t1, t2, t3, t4)
{
var a = elt(abcd, 0);
var b = elt(abcd, 1);
var c = elt(abcd, 2);
var d = elt(abcd, 3);
a = ii(a, b, c, d, elt2(x, i, offset, 0), 6, t1);
d = ii(d, a, b, c, elt2(x, i, offset, 7), 10, t2);
c = ii(c, d, a, b, elt2(x, i, offset, 14), 15, t3);
b = ii(b, c, d, a, elt2(x, i, offset, 21), 21, t4);
return combine (a, b, c, d);
}
/*
* A WML Script implementation of the Ord function
* which seems to be strangely missing.
* Copyright (C) Simon Wistow, 2001
*/
extern function ord_string (str)
{
var return_str;
for (var i = 0; i< String.length(str); i++){
if (i>0)
return_str += '|';
return_str += ord(String.charAt(str,i));
}
return return_str;
}
extern function ord (char)
{
var ordstring = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
return String.find(ordstring, char) + 32;
}
/*
* A WML Script implementation of the Secure Hash Algorithm, SHA-1
* as defined in FIPS PUB 180-1
* Digest Algorithm, as defined in RFC 1321.
* Copyright (C) Simon Wistow, 2001
*/
/*
* Convert a 32-bit number to a hex string with ms-byte first
*/
use url ordlib "ord.wmls";
function hex(num)
{
var hex_chr = "0123456789abcdef";
var str = "";
for(var j = 7; j >= 0; j--)
str += String.charAt(hex_chr, num >> (j * 4) & 0x0F);
return str;
}
/*
* Convert a string to a sequence of 16-word blocks, stored as an array.
* Append padding bits and the length, as described in the SHA1 standard.
*/
function str2blks_SHA1(str)
{
var nblk = ((String.length(str) + 8) >> 6) + 1;
var blks = "0";
var ord_str = ordlib#ord_string(str);
for(var i = 1; i < nblk * 16; i++)
blks += '|0';
for(i = 0; i <= String.length(str); i++)
{
var temp = String.elementAt(blks, i>>2, '|');
if (i != String.length(str))
temp |= String.charAt(ord_str,i) << (24 - (i % 4) * 8);
else
temp |= 0x80 << (24 - (i % 4) * 8);
blks = String.replaceAt(blks, temp, i>>2, '|');
}
blks = String.replaceAt(blks, String.length(str) * 8, nblk * 16 - 1, '|');
return blks;
}
/*
* Add integers, wrapping at 2^32
*/
function add(x, y)
{
return ((x&0x7FFFFFFF) + (y&0x7FFFFFFF)) ^ (x&0x80000000) ^ (y&0x80000000);
}
/*
* Bitwise rotate a 32-bit number to the left
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function kt(t)
{
if(t < 20) return 0x5A827999;
if(t < 40) return 0x6ED9EBA1;
if(t < 60) return 0x8F1BBCDC;
return 0xCA62C1D6;
}
/*
* Take a string and return the hex representation of its SHA-1.
*/
function calcSHA1(str)
{
var x = str2blks_SHA1(str);
var w = "0";
for (var k=0; k<79; k++)
{
w += "|0";
}
var a = 0x67452301;
var b = 0xEFCDAB89;
var c = 0x98BADCFE;
var d = 0x10325476;
var e = 0xC3D2E1F0;
for(var i = 0; i < String.elements(x,'|'); i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16)
w = String.replaceAt(w,String.elementAt(x,i + j,'|'),j,'|');
else
w= String.replaceAt(w,rol(String.elementAt(w,j-3,'|') ^ String.elementAt(w,j-8,'|') ^ String.elementAt(w,j-14,'|') ^ String.elementAt(w,j-16,'|'), 1),j,'|');
var t = add(add(rol(a, 5), ft(j, b, c, d)), add(add(e, String.elementAt(w,j,'|')), kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = add(a, olda);
b = add(b, oldb);
c = add(c, oldc);
d = add(d, oldd);
e = add(e, olde);
}
return hex(a) + hex(b) + hex(c) + hex(d) + hex(e);
}
extern function hash (var_to_set, string)
{
WMLBrowser.setVar(var_to_set, calcSHA1(URL.unescapeString(string)));
WMLBrowser.refresh ();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment