UNPKG

@aladas-org/cryptocalc

Version:
432 lines (318 loc) 15.5 kB
// ====================================================================================== // =========================== draw_entropy_mouse_move.js =========================== // ====================================================================================== "use strict"; const DrawE_Mouse = { CANVAS_WIDTH: 500, CANVAS_HEIGHT: 150, DOT_SIZE: 9, BG_COLOR: 220, DRAW_AREA_MARGIN: 10, MIN_BOTTOM_MARGIN: 10, MAX_BOTTOM_MARGIN: 25, MARGINS: { "left": 10, "right": 10, "top": 10, "bottom": 25 }, MIN_THRESHOLD: 20, THRESHOLD_VARIANCE: 60, STATE_INIT: "STATE_INIT", STATE_INPUT: "STATE_INPUT", STATE_END: "STATE_END" }; // DrawE_Mouse const decimalToHex = (decimal) => { if (decimal < 0 || decimal > 255) { throw new Error('Number must be between 0 and 255'); } // Convert to hex and pad with leading zero if needed const hex = decimal.toString(16); return hex.length === 1 ? '0' + hex : hex; }; // decimalToHex() const xor_bytes = (a, b) => { // Ensure values are within byte range (0-255) const byte_A = a & 0xFF; const byte_B = b & 0xFF; return byte_A ^ byte_B; }; // xor_bytes() const draw_progress_bar = ( p, current_point_count, max_points ) => { let pbar_x = 5; let pbar_y = DrawE_Mouse.CANVAS_HEIGHT - DrawE_Mouse.MAX_BOTTOM_MARGIN + 10; let pbar_width = DrawE_Mouse.CANVAS_WIDTH - 10; let pbar_height = 10; let WHITE_COLOR = p.color(255, 255, 255); p.fill( WHITE_COLOR ); p.rect( pbar_x, pbar_y, pbar_width, pbar_height ); let GREEN_COLOR = p.color(0, 255, 0); let bar_x = 7; let bar_y = DrawE_Mouse.CANVAS_HEIGHT - DrawE_Mouse.MAX_BOTTOM_MARGIN + 12; let bar_width = pbar_width * (current_point_count / max_points) - 4; let bar_height = 6; p.fill( GREEN_COLOR ); p.rect( bar_x, bar_y, bar_width, bar_height ); }; // draw_progress_bar() const pointTo2DigitHex = (point, max_X, max_Y) => { // Combine normalized coordinates into a single value (0-255) const normalized_X = ( point.x / max_X ) * 15; // 0-15 (4 bits) const normalized_Y = ( point.y / max_Y ) * 15; // 0-15 (4 bits) // Pack into single byte: upper 4 bits = X, lower 4 bits = Y const packed_value = (Math.round(normalized_X) << 4) | Math.round(normalized_Y); // Convert to 2-digit hex return packed_value.toString(16).padStart(2, '0'); } // pointTo2DigitHex() const generate_random_point = () => { let margin_X = DrawE_Mouse.MARGINS["left"] + DrawE_Mouse.MARGINS["right"]; let margin_Y = DrawE_Mouse.MARGINS["top"] + DrawE_Mouse.MARGINS["bottom"]; let rand_point = { x: 0, y: 0 }; rand_point.x = getRandomInt( DrawE_Mouse.CANVAS_WIDTH - margin_X ) + DrawE_Mouse.MARGINS["left"]; rand_point.y = getRandomInt( DrawE_Mouse.CANVAS_HEIGHT - margin_Y ) + DrawE_Mouse.MARGINS["top"]; return rand_point; }; // generate_random_point() class DrawEntropyMouseMove { static #Key = Symbol(); static #Singleton = new DrawEntropyMouseMove( this.#Key ); static New_btn_cb_initialized = false; static GetInstance() { if ( DrawEntropyMouseMove.#Singleton == undefined ) { DrawEntropyMouseMove.#Singleton = new DrawEntropyMouseMove(DrawEntropyMouseMove.#Key); } if ( ! DrawEntropyMouseMove.New_btn_cb_initialized ) { let DrawE_Mouse_obj = DrawEntropyMouseMove.#Singleton; DrawE_Mouse_obj.setEventHandler( ENTROPY_SRC_MOUSE_MOVE_NEW_BTN_ID, 'click', (evt) => { DrawE_Mouse_obj.onNewEntropy(); } ); DrawEntropyMouseMove.New_btn_cb_initialized = true; } return DrawEntropyMouseMove.#Singleton; } // DrawEntropyMouseMove.GetInstance() // ** Private constructor ** constructor( key ) { if ( key !== DrawEntropyMouseMove.#Key ) { throw new TypeError("'DrawEntropyMouseMove' constructor is private"); } this.state = DrawE_Mouse.STATE_INIT; this.canvas = undefined; this.p5_obj = new p5(this.pattern_generator_sketch, 'DrawEntropyMouseMove'); this.points = []; this.random_bytes = []; this.threshold = DrawE_Mouse.MIN_THRESHOLD + getRandomInt(DrawE_Mouse.THRESHOLD_VARIANCE); this.entropy = ""; this.WHITE_COLOR = this.p5_obj.color(255, 255, 255); this.BLACK_COLOR = this.p5_obj.color(0, 0, 0); this.RED_COLOR = this.p5_obj.color(255, 0, 0); this.YELLOW_COLOR = this.p5_obj.color(255, 255, 0); this.init(32); } // ** Private constructor ** init( required_byte_count_arg ) { // console.log(">> [DrawE_Mouse] init"); this.points = []; this.random_bytes = []; this.entropy = ""; DrawE_Mouse.MARGINS["bottom"] = DrawE_Mouse.MAX_BOTTOM_MARGIN; if (required_byte_count_arg == undefined) required_byte_count_arg = 32; this.required_byte_count = required_byte_count_arg; // this.previous_position = { x: -1, y: -1 }; this.previous_position = generate_random_point(); this.state = DrawE_Mouse.STATE_INIT; // this.p5_obj.background(DrawE_Mouse.BACKGROUND_COLOR); } // init() // 'Mouse move' XOR crypto.random() computeMixedEntropy() { let mixed_bytes = []; for ( let i=0; i < this.random_bytes.length; i++ ) { let random_byte = this.random_bytes[i]; let mixed_byte_hex = decimalToHex( getRandomByte() ); mixed_bytes.push( mixed_byte_hex ); } // let entropy = this.random_byte.join('').toString(); let mixed_entropy = mixed_bytes.join('').toString(); return mixed_entropy; } // computeMixedEntropy() generateEntropy( required_byte_count ) { if (required_byte_count == undefined) required_byte_count = 32; this.required_byte_count = required_byte_count; // console.log(">> [DrawE_Mouse] generateEntropy required_byte_count: " + required_byte_count); this.init( required_byte_count ); DrawE_Mouse.MARGINS["bottom"] = DrawE_Mouse.MIN_BOTTOM_MARGIN; let margins = DrawE_Mouse.MARGINS; let margin_X = margins["left"] + margins["right"]; this.p5_obj.background( DrawE_Mouse.BG_COLOR ); this.previous_position = generate_random_point(); this.p5_obj.fill( this.YELLOW_COLOR ); this.p5_obj.circle( this.previous_position.x, this.previous_position.y, DrawE_Mouse.DOT_SIZE ); this.p5_obj.circle( this.previous_position.x, this.previous_position.y, DrawE_Mouse.DOT_SIZE - 2 ); const drawLineBetweenCircles = (circle1, circle2, radius) => { // Calculate the angle between centers let angle = Math.atan2(circle2.y - circle1.y, circle2.x - circle1.x); // Calculate intersection points let startPoint = { x: circle1.x + Math.cos(angle) * radius, y: circle1.y + Math.sin(angle) * radius }; let endPoint = { x: circle2.x - Math.cos(angle) * radius, y: circle2.y - Math.sin(angle) * radius }; // drawLineBetweenCircles() // Draw the line this.p5_obj.line(startPoint.x, startPoint.y, endPoint.x, endPoint.y); return { start: startPoint, end: endPoint }; }; // drawLineBetweenCircles() for ( let i=0; i < this.required_byte_count; i++ ) { // console.log("> generateEntropy(" + i + ")" ); let threshold = DrawE_Mouse.MIN_THRESHOLD + getRandomInt(DrawE_Mouse.THRESHOLD_VARIANCE); let hypotenuse = 0; // console.log("> generateEntropy(" + i + ") threshold: " + threshold); let rand_x = 0; let rand_y = 0; let delta = { x: 0, y: 0 }; let rand_point = { x: 0, y: 0 }; while ( hypotenuse < threshold ) { // console.log("> generateEntropy(" + i + ") : hypotenuse: " + hypotenuse); rand_point = generate_random_point(); delta.x = Math.abs(rand_point.x - this.previous_position.x); delta.y = Math.abs(rand_point.y - this.previous_position.y); hypotenuse = Math.round(Math.sqrt(delta.x*delta.x + delta.y*delta.y)); } this.addPoint( rand_point ); // this.p5_obj.line( rand_point.x, rand_point.y, this.previous_position.x, this.previous_position.y ); drawLineBetweenCircles(rand_point, this.previous_position, DrawE_Mouse.DOT_SIZE / 2); this.p5_obj.fill(this.YELLOW_COLOR); this.p5_obj.circle( rand_point.x, rand_point.y, DrawE_Mouse.DOT_SIZE ); this.p5_obj.circle( rand_point.x, rand_point.y, DrawE_Mouse.DOT_SIZE - 2 ); this.previous_position = { x: rand_point.x, y: rand_point.y }; } // let entropy = this.random_bytes.join('').toString(); let entropy = this.computeMixedEntropy(); // NB: seems "not enuff entropy" indeed // console.log("> DrawE_Mouse.generateEntropy:\n " + entropy); return entropy; } // generateEntropy() onNewEntropy() { console.log(">> DrawE_Mouse.onNewEntropy"); this.init( this.required_byte_count ) this.p5_obj.background( DrawE_Mouse.BG_COLOR ); this.previous_position = generate_random_point(); let margin = DrawE_Mouse.DRAW_AREA_MARGIN; DrawE_Mouse.MARGINS["bottom"] = 25; let margins = DrawE_Mouse.MARGINS; let margin_X = margins["left"] + margins["right"]; let margin_Y = margins["top"] + margins["bottom"]; let ranged_point = { x: this.previous_position.x, y: this.previous_position.y }; // const random_byte = pointTo2DigitHex // ( ranged_point, DrawE_Mouse.CANVAS_WIDTH - margin_X, DrawE_Mouse.CANVAS_HEIGHT - margin_Y ); this.addPoint( this.previous_position ); this.p5_obj.fill( this.WHITE_COLOR ); this.p5_obj.circle(this.previous_position.x, this.previous_position.y, 9); draw_progress_bar( this.p5_obj, 1, this.required_byte_count); this.state = DrawE_Mouse.STATE_INPUT; } // onNewEntropy() addPoint( new_point ) { this.points.push( new_point ); let margins = DrawE_Mouse.MARGINS; let margins_HORIZONTAL = margins["left"] + margins["right"]; let margins_VERTICAL = margins["top"] + margins["bottom"]; let origin_point = { x: new_point.x - margins["left"], y: new_point.y - margins["top"] }; const new_byte = pointTo2DigitHex( origin_point, DrawE_Mouse.CANVAS_WIDTH - margins_HORIZONTAL, DrawE_Mouse.CANVAS_HEIGHT- margins_VERTICAL ); this.random_bytes.push( new_byte ); } // addPoint() getEntropy() { if ( this.entropy == '' ) return ''; // console.log(">> [DrawE_Mouse] getEntropy:\n " + this.entropy); return this.entropy; } // getEntropy() isHidden() { // console.log(">> [DrawE_Mouse] isHidden " + ENTROPY_SRC_MOUSE_MOVE_CONTAINER_ID); let container_elt = document.getElementById(ENTROPY_SRC_MOUSE_MOVE_CONTAINER_ID); // console.log(">> [DrawE_Mouse] container_elt " + container_elt); if ( container_elt != undefined ) { let visibility = window.getComputedStyle(container_elt).display; // console.log("> DrawE_Mouse.visibility: " + visibility); if ( visibility === "none" ) { return true; } } return false; } // isHidden() onMouseMoved( x_arg, y_arg ) { if ( DrawEntropyMouseMove.GetInstance().isHidden() ) { // console.log(">> return because HIDDEN: "); return; } if ( this.state != DrawE_Mouse.STATE_INPUT ) { // console.log(">> return because state is not STATE_INPUT"); return; } let mouse_point = { x: x_arg, y: y_arg }; // console.log(">> DrawE_Mouse.onMouseMoved state: " + this.state); // let margin = DrawE_Mouse.DRAW_AREA_MARGIN; let margins = DrawE_Mouse.MARGINS; draw_progress_bar( this.p5_obj, this.random_bytes.length, this.required_byte_count); if ( mouse_point.x >= margins["left"] && mouse_point.x <= DrawE_Mouse.CANVAS_WIDTH - margins["right"] && mouse_point.y >= margins["top"] && mouse_point.y <= DrawE_Mouse.CANVAS_HEIGHT - margins["bottom"] ) { // console.log(">> DrawE_Mouse.onMouseMoved (" + this.random_values.length + ") " // + "x: " + x_arg + " y:" + y_arg); let dX = Math.abs(mouse_point.x - this.previous_position.x); let dY = Math.abs(mouse_point.y - this.previous_position.y); let hypotenuse = Math.round(Math.sqrt(dX*dX + dY*dY)); if ( hypotenuse >= this.threshold ) { this.addPoint( mouse_point ); this.threshold = DrawE_Mouse.MIN_THRESHOLD + getRandomInt(DrawE_Mouse.THRESHOLD_VARIANCE); this.p5_obj.line( x_arg, y_arg, this.previous_position.x, this.previous_position.y ); this.previous_position = { x: x_arg, y: y_arg }; this.p5_obj.fill( this.WHITE_COLOR ); this.p5_obj.circle( x_arg, y_arg, DrawE_Mouse.DOT_SIZE ); draw_progress_bar( this.p5_obj ); if ( this.random_bytes.length >= this.required_byte_count ) { this.entropy = this.random_bytes.join('').toString(); let mixed_entropy = this.computeMixedEntropy(); // console.log(">> DrawE_Mouse.onMouseMoved >>>>>> mixed_entropy\n: " + mixed_entropy); this.entropy = mixed_entropy; console.log(">> DrawE_Mouse.onMouseMoved Entropy\n: " + this.entropy); for (let i=0; i < this.points.length; i++) { let current_point = this.points[i]; this.p5_obj.fill( this.YELLOW_COLOR ); this.p5_obj.circle( current_point.x, current_point.y, DrawE_Mouse.DOT_SIZE -2 ); } draw_progress_bar( this.p5_obj, this.required_byte_count, this.required_byte_count ); this.p5_obj.fill( this.WHITE_COLOR ); this.state = DrawE_Mouse.STATE_END; const new_event_obj = new CustomEvent( CUSTOM_EVT_UPDATE_ENTROPY, { detail: { 'entropy': this.entropy } } ); document.body.dispatchEvent( new_event_obj ); } } } } // onMouseMoved() pattern_generator_sketch( p ) { // p could be any variable name p.setup = async () => { // console.log(">> DrawE_Mouse.Initialize [P5] pattern_generator_sketch.setup()"); DrawEntropyMouseMove.canvas = p.createCanvas( DrawE_Mouse.CANVAS_WIDTH, DrawE_Mouse.CANVAS_HEIGHT ); DrawEntropyMouseMove.canvas.parent(ENTROPY_SRC_MOUSE_MOVE_DIV_ID); p.background(DrawE_Mouse.BG_COLOR); }; // setup() p.getP5 = function() { return p; }; // getP5() p.getID = function() { return "DrawEntropyMouseMove"; }; // getID() // p.mousePressed = function() { // } // mousePressed() p.mouseMoved = () => { let mouse_X = Math.round(p.mouseX); let mouse_Y = Math.round(p.mouseY); DrawEntropyMouseMove.GetInstance().onMouseMoved( mouse_X, mouse_Y ); } // p.mouseMoved() p.draw = function() { }; // https://p5js.org/examples/advanced-data-load-saved-json.html // Put any asynchronous data loading in preload to complete before "setup" is run p.preload = () => { }; // preload() } // pattern_generator_sketch setEventHandler( elt_id, event_name, handler_function ) { // console.log(">> DrawE_Mouse.setEventHandler elt_id: " + elt_id); let elt = document.getElementById( elt_id ); // console.log(">> DrawE_Mouse.setEventHandler elt: " + elt); if ( elt != undefined ) { elt.addEventListener(event_name, handler_function ); } } // setEventHandler() } // DrawEntropyMouseMove // DrawEntropyMouseMove.GetInstance();