Generating identical pseudorandom numbers on client and server - javascript

I have a web application using JavaScript on the client side and C# on the server side. I need to be able to generate sets pseudorandom numbers - given a shared seed - that are identical on the client and server sides. Is there a standard way of doing this? Obviously it's no good using the built-in PRNG libraries for the respective languages because their algorithms are going to differ.
I don't want to use a server endpoint to provide the client with the random numbers because my client application requires quick responses and that would add latency. It would work but wouldn't be ideal.

Here's a javascript implementation of the C version of xorshift128+. Per the wikipedia article, the xorshift128+ pseudo random number generator (PRNG) passes BigCrush (empirical randomness testing).
Note that xorshift128+ is used by major browsers when implementing Math.random, so it's a solid algorithm, although not crypto solid...
Note also that the local variables within method nextValue make use of a BigUint64Array, as this automatically reduces any intermediate results to 64 bits.
class XorShift128 {
#state;
static bitMask64 = ( 1n << 64n ) - 1n;
static bitMask32 = ( 1n << 32n ) - 1n
constructor( uint128Seed ) {
this.#state = new BigUint64Array( [ ( uint128Seed >> 64n ) & XorShift128.bitMask64, uint128Seed & XorShift128.bitMask64 ] );
}
get nextValue() {
let r = new BigUint64Array( this.#state );
// C version t = r[0], s = r[1]
this.#state[ 0 ] = r[ 1 ];
r[ 0 ] ^= r[ 0 ] << 23n;
r[ 0 ] ^= r[ 0 ] >> 18n;
r[ 0 ] ^= r[ 1 ] ^ ( r[ 1 ] >> 5n );
this.#state[ 1 ] = r[ 0 ];
return Number( ( r[ 0 ] + r[ 1 ] ) & XorShift128.bitMask32 );
}
}
console.log( `Set the seed to 0x8a5cd789635d2dff121fd2155c472f96n and generate 5 values...` );
let PRNG0 = new XorShift128( 0x8a5cd789635d2dff121fd2155c472f96n );
for ( let i = 0; i < 5; i++ ) {
console.log( PRNG0.nextValue );
}
console.log( `Let's do it again...` );
let PRNG1 = new XorShift128( 0x8a5cd789635d2dff121fd2155c472f96n );
for ( let i = 0; i < 5; i++ ) {
console.log( PRNG1.nextValue );
}
For completeness sake, here's the same algorithm in C.
//gcc 7.4.0
#include <stdint.h>
#include <stdio.h>
struct xorshift128p_state {
uint64_t x[2];
};
/* The state must be seeded so that it is not all zero */
uint64_t xorshift128p(struct xorshift128p_state *state)
{
uint64_t t = state->x[0];
uint64_t const s = state->x[1];
state->x[0] = s;
t ^= t << 23;
t ^= t >> 18;
t ^= s ^ (s >> 5);
state->x[1] = t;
return t + s;
}
main() {
struct xorshift128p_state seed;
seed.x[0] = 0x8a5cd789635d2dff;
seed.x[1] = 0x121fd2155c472f96;
uint64_t bitMask32 = ( 1ULL << 32 ) - 1ULL;
int i;
for ( i =0; i < 5; i++ ) {
uint64_t rv = xorshift128p( &seed );
printf( "%ld\n", rv & bitMask32 );
}
}
C Code Snippet

Add an API endpoint on the server in c# to return individual or an array of random numbers, then call that from the client.
calls to the server do not have to be inefficient, depending on your logic and the frequency of the call, it might even make sense to call this from the server, especially if consistency of the values is so important, this might be an X-Y Problem, what is the frequency of the calls, what is the highest latency that you can tolerate and what type of response times are you recording from your implementation.
Yes, there is a standard solution to problems like this (replicating logic in the client and the server) and that is to use the same random number generator algorithm and the same seed value. This is for instance how we can replay specific hands in card games.
A pure C# solution that allows you to use the same code in the client and the server would be to consider Blazor instead of javascript. Other solutions would be to implement your own algorithm or to find another one that has been ported to both C# and javascript.

So basically I've come to the conclusion that the only really reliable way I could get exactly the same PRNG on both the server and client side is to use the same language on both sides - for example C# using Blazor on the client-side and C#.NET on the server-side - and to create a class in that language that has an identical implementation for the server-side and client-side code, which would get shared.
A good class to copy/paste for such an implementation would probably be the XoshiroImpl random number generator class which seems to be the latest PRNG implementation being used by .NET core.
As it is I'm using JS for the client and C# for the server, so I had to solve the problem in a different way.

Related

Finding out CIDR for a single IP (v4/v6) Address (TypeScript)

I`m working on a project using TypeScript and have access to a key-value based storage. The requirement is to find data related to a single IP (match key).
Unfortunately the key is always a CIDR covering a lot of IP's (to save storage due to many records). During my tests I was unable to find the correct CIDR belonging to a specific IP.
Example data:
"103.21.244.0/24" - "data, lorem ipsum, etc"
Example IP to find:
"103.21.244.1"
I have tested several libraries like: ip-address, ip-num, ip-to-int, ipaddr.js and more, but I am unable to get the result I want.
Maybe I am just being dumb and do not understand the IP specification correctly, or maybe I am just misusing these libraries, please enlighten me.
Surely there has to be a way without calling external API's (like RIPE) and without having to store billions of IP's instead of their CIDR.
Essentially the requirement is quite simple: "find this KEY (in CIDR) by this IP (v4 or v6)".
Any help, advice, example solutions are highly appreciated.
IP address can be converted to a single number. The a.b.c.d form is a just base-256 representation of a 32-bit number. Convert both the address and the subnet mask to integer. Then use "bitwise and" operation to apply the mask to the target IP addresses and compare with the network address.
function addrToNumber(addr)
{
return addr.split(".").reduce((acc,cur,i)=> acc += (Number(cur) << ( (3-i) * 8) ) ,0)
}
function subnetMaskToNumber(mask)
{
return (0xffffffff << (32 - Number(mask))) & 0xffffffff;
}
const cidr = "103.21.244.0/24";
const [networkAddr,subnetMask] = cidr.split("/");
const ipAddr = "103.21.244.1";
const match = (addrToNumber(ipAddr) & subnetMaskToNumber(subnetMask)) == addrToNumber(networkAddr)
console.log(match);
To generate all possible CIDR for an IP address:
function addrToNumber(addr)
{
return addr.split(".").reduce((acc,cur,i)=> acc += (Number(cur) << ( (3-i) * 8) ) ,0)
}
function numberToAddr(num)
{
return `${(num >> 24) & 0xff}.${(num >> 16) & 0xff}.${(num >> 8) & 0xff}.${num & 0xff}`
}
const ipAddr = "103.21.244.1";
const ipValue = addrToNumber(ipAddr);
let possibleCIDR = [...Array(33)].map((_,i)=>{
let mask = i == 0 ? 0 : (0xffffffff << (32 - i)) >>> 0;
return `${numberToAddr(ipValue & mask)}/${i}`;
});
console.log(possibleCIDR);
To generate possible CIDR for IPv6, zeros compression not handled.
const ipv6 = "2001:db8:85a3:8d3:1319:8a2e:370:7348";
const groups = ipv6.split(":");
let possibleCIDR = [...Array(129)].map((_,i)=>{
let groupIndex = Math.floor(i / 16);
let mask = (i % 16) ? (0xffff << (16 - (i % 16))) & 0xffff : 0;
return groups.map((value,j)=>{
return (j < groupIndex ? value : j == groupIndex ? parseInt(value,16) & mask : 0).toString(16)
}).join(":") + `/${i}`;
});
console.log(possibleCIDR);

Different blowfish encryption results

I am trying to replicate a particular function from our SAP system to a web site and a part of the flow is a blowfish encryption. I looked around for Blowfish encryption libraries for Javascript and implemented it into my js code.
However, upon comparison with the original SAP flow, the results of our blowfish encryptions are different.
The only thing that's different is that SAP blowfish uses UTF-16LE. I've tried converting my password and the text to UTF-16LE but I cannot get the same results from the original system.
I've found these two codes while searching around (these 2 converts/decodes from UTF8-UTF16 and vice versa)
function strEncodeUTF16(str) {
var byteArray = new Uint8Array(str.length * 2);
for (var i = 0; i < str.length; i++) {
byteArray[i*2] = str.charCodeAt(i); // & 0xff;
byteArray[i*2+1] = str.charCodeAt(i) >> 8; // & 0xff;
}
return String.fromCharCode.apply(String,byteArray);
}
function decodeUTF16LE( binaryStr ) {
var cp = [];
for( var i = 0; i < binaryStr.length; i+=2) {
cp.push(
binaryStr.charCodeAt(i) |
( binaryStr.charCodeAt(i+1) << 8 )
);
}
return String.fromCharCode.apply( String, cp );
}
The blowfish library I'm using is from the Dojo Toolkit:
Blowfish.js from Dojo Toolkit 1.8.1
A sample test case would be:
Password: 7F30742A2
Text: 329
Result: B33663DFAC049492
However, when I try it on my end
var encrypted = blowfish.encrypt(id, key, {outputType:1, cipherMode: 0});
My result is:
ef701b0e904b10c3
I am not sure where the difference is happening. Any thoughts?

Script HP Test and Attack system in Imacro

I'm trying to create a Script or Macro that simply checks my HP, and then attacks or heals. My macros work, I just can't get them to play with javascript. HP Test.iim Extracts the HP from the web page. I want to take that Extracted number and make it a variable. I'm new to scripting, maybe I can get some help.
New script based on code below (thanks for that)
ten = 1
while (ten = 1) {
iimPlay("Hunt/HP Test.iim");
var extract = iimGetLastExtract ();
var HP=extract.split("/")[0];
HP=parseInt(HP);
iimSet ( "HP", HP )
if ( HP >= 1 )
{
iimPlay ("Hunt/Attack.iim")
}
else
{
iimPlay ("Hunt/Heal.iim")
}
}
IT Works! Thanks much, I've been working on that for a long time!
iimPlay("HP Test.iim");
var extract = iimGetLastExtract ();
iimSet ( "HP", extract )
if ( extract >= 1 )
{
iimPlay ("Attack.iim")
}
else
{
iimPlay ("Heal.iim")
}
This code might not work but you will get an idea how the syntax works.
Edit: example of methods >>> http://jsfiddle.net/KRV5a/

Pre-processing Emulator for JavaScript ( Timing / Debug Example )

In C++ you can omit compiling debug code by using pre-processing directives in order to keep your compiled code fast and not hindered by debug code not needed in production.
Is there a correlative way to do this in JavaScript? What I have been doing in the past is commenting out debug code, but I want a cleaner way to do it.
An example below shows 4 if statements that activate if debug is set to true. However in production I don't want this checked 4 times when I know it will be set to false. As I mentioned I could cram it into one line and comment it out...but I want a clean way to do it?
/**
** cType
*/
function cType( o_p ) {
if( debug ) {
var t1, t2, t3, t4, i1, i2, i3; t1 = new Date().getTime();
}
o_p = MType[ o_p.model ].pre( o_p );
if ( o_p.result !== 'complete' ) {
if( debug ) {
t2 = new Date().getTime();
console.log( '---------------Send to Server - object_pipe: \n ' + o_p.toSource() );
}
var string_pipe = JSON.stringify( o_p );
cMachine( 'pipe=' + string_pipe , function( string_pipe ) {
if( debug ) {
console.log( '---------------Receive from Server - object_pipe: \n ' + string_pipe );
t3 = new Date().getTime();
}
MType[ o_p.model ].post( JSON.parse( string_pipe ) );
if( debug ) {
t4 = new Date().getTime(); i1 = t2-t1 ; i2 = t3-t2 ; i3 = t4-t3;
console.log( '---------------Pre, Transit, Post = ', i1, i2, i3 );
}
} );
}
}
You can always pass it through c preprocessor like:
gcc -E input.js -o output.js
This will allow you to use #if and even include and macros.
If you use RequireJS, you can use build pragmas and even the has.js integration to disable/enable code fragments at optimization (minification) time.
No, Javascript is not compiled, it's interpreted. Therefore it's impossible to have preprocessing directives unless you pass non-standard Javascript - it probably won't be Javascript anymore - code through another utility.

Best way to generate unique ids client-side (with Javascript)

I need to generate unique ids in the browser. Currently, I'm using this:
Math.floor(Math.random() * 10000000000000001)
I'd like to use the current UNIX time ((new Date).getTime()), but I'm worried that if two clients generate ids at the exact same time, they wouldn't be unique.
Can I use the current UNIX time (I'd like to because that way ids would store more information)? If not, what's the best way to do this (maybe UNIX time + 2 random digits?)
you can create a GUID using the following links:
http://softwareas.com/guid0-a-javascript-guid-generator
Create GUID / UUID in JavaScript?
This will maximise your chance of "uniqueness."
Alternatively, if it is a secure page, you can concatenate the date/time with the username to prevent multiple simultaneous generated values.
https://github.com/uuidjs/uuid provides RFC compliant UUIDs based on either timestamp or random #'s. Single-file with no dependencies, supports timestamp or random #-based UUIDs, uses native APIs for crypto-quality random numbers if available, plus other goodies.
In modern browser you can use crypto:
var array = new Uint32Array(1);
window.crypto.getRandomValues(array);
console.log(array);
var c = 1;
function cuniq() {
var d = new Date(),
m = d.getMilliseconds() + "",
u = ++d + m + (++c === 10000 ? (c = 1) : c);
return u;
}
Here is my javascript code to generate guid. It does quick hex mapping and very efficient:
AuthenticationContext.prototype._guid = function () {
// RFC4122: The version 4 UUID is meant for generating UUIDs from truly-random or
// pseudo-random numbers.
// The algorithm is as follows:
// Set the two most significant bits (bits 6 and 7) of the
// clock_seq_hi_and_reserved to zero and one, respectively.
// Set the four most significant bits (bits 12 through 15) of the
// time_hi_and_version field to the 4-bit version number from
// Section 4.1.3. Version4
// Set all the other bits to randomly (or pseudo-randomly) chosen
// values.
// UUID = time-low "-" time-mid "-"time-high-and-version "-"clock-seq-reserved and low(2hexOctet)"-" node
// time-low = 4hexOctet
// time-mid = 2hexOctet
// time-high-and-version = 2hexOctet
// clock-seq-and-reserved = hexOctet:
// clock-seq-low = hexOctet
// node = 6hexOctet
// Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
// y could be 1000, 1001, 1010, 1011 since most significant two bits needs to be 10
// y values are 8, 9, A, B
var guidHolder = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
var hex = '0123456789abcdef';
var r = 0;
var guidResponse = "";
for (var i = 0; i < 36; i++) {
if (guidHolder[i] !== '-' && guidHolder[i] !== '4') {
// each x and y needs to be random
r = Math.random() * 16 | 0;
}
if (guidHolder[i] === 'x') {
guidResponse += hex[r];
} else if (guidHolder[i] === 'y') {
// clock-seq-and-reserved first hex is filtered and remaining hex values are random
r &= 0x3; // bit and with 0011 to set pos 2 to zero ?0??
r |= 0x8; // set pos 3 to 1 as 1???
guidResponse += hex[r];
} else {
guidResponse += guidHolder[i];
}
}
return guidResponse;
};
You can always run a test against existing IDs in the set to accept or reject the generated random number recursively.
for example:
const randomID = function(){
let id = Math.floor(Math.random() * 10000000000000001) + new Date();
if (idObjectArray.contains(id)) {
randomID;
} else {
idObjectArray.push(id);
}
};
This example assumes you would just be pushing the id into a 1D array, but you get the idea. There shouldn't be many collisions given the uniqueness of the random number with the date, so it should be efficient.
There are two ways to achieve this
js const id = Date.now().toString()
While this does not guarantee uniqueness (When you are creating multiple objects within 1ms), this will work on a practical level, since it is usually not long before the objects on the client are sent to a real server.
If you wanted to create multiple records withing 1ms, I suggest using the code below
const { randomBytes } = require("crypto");
// 32 Characters
const id = randomBytes(16).toString("hex");
It works similar to a uuid4 without needing to add an external library (Assuming you have access to NodeJs at some point)

Categories