OpenWebNet password

From Rosetta Code
Revision as of 19:21, 3 December 2017 by Tim-brown (talk | contribs) (→‎=={{header|Racket}}==: stub added)
OpenWebNet password is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Calculate the password requested by ethernet gateways from the Legrand / Bticino MyHome OpenWebNet home automation system when the user's ip address is not in the gateway's whitelist

Note: Factory default password is '12345'. Changing it is highly recommended !

conversation goes as follows

← *#*1##
→ *99*0##
← *#603356072##

at which point a password should be sent back, calculated from the "password open" that is set in the gateway, and the nonce that was just sent

→ *#25280520##
← *#*1##

D

Translation of: Python

<lang d>import std.stdio, std.string, std.conv, std.ascii, std.algorithm;

ulong ownCalcPass(in ulong password, in string nonce) pure nothrow @safe @nogc in {

   assert(nonce.representation.all!isDigit);

} body {

   enum ulong m_1        = 0x_FFFF_FFFF_UL;
   enum ulong m_8        = 0x_FFFF_FFF8_UL;
   enum ulong m_16       = 0x_FFFF_FFF0_UL;
   enum ulong m_128      = 0x_FFFF_FF80_UL;
   enum ulong m_16777216 = 0X_FF00_0000_UL;
   auto flag = true;
   ulong num1 = 0, num2 = 0;
   foreach (immutable char c; nonce) {
       num1 &= m_1;
       num2 &= m_1;
       switch (c) {
           case '0':
               num1 = num2;
               break;
           case '1':
               if (flag)
                   num2 = password;
               flag = false;
               num1 = num2 & m_128;
               num1 = num1 >> 7;
               num2 = num2 << 25;
               num1 = num1 + num2;
               break;
           case '2':
               if (flag)
                   num2 = password;
               flag = false;
               num1 = num2 & m_16;
               num1 = num1 >> 4;
               num2 = num2 << 28;
               num1 = num1 + num2;
               break;
           case '3':
               if (flag)
                   num2 = password;
               flag = false;
               num1 = num2 & m_8;
               num1 = num1 >> 3;
               num2 = num2 << 29;
               num1 = num1 + num2;
               break;
           case '4':
               if (flag)
                   num2 = password;
               flag = false;
               num1 = num2 << 1;
               num2 = num2 >> 31;
               num1 = num1 + num2;
               break;
           case '5':
               if (flag)
                   num2 = password;
               flag = false;
               num1 = num2 << 5;
               num2 = num2 >> 27;
               num1 = num1 + num2;
               break;
           case '6':
               if (flag)
                   num2 = password;
               flag = false;
               num1 = num2 << 12;
               num2 = num2 >> 20;
               num1 = num1 + num2;
               break;
           case '7':
               if (flag)
                   num2 = password;
               flag = false;
               num1 = num2 & 0xFF00UL;
               num1 = num1 + ((num2 & 0xFFUL) << 24);
               num1 = num1 + ((num2 & 0xFF0000UL) >> 16);
               num2 = (num2 & m_16777216) >> 8;
               num1 = num1 + num2;
               break;
           case '8':
               if (flag)
                   num2 = password;
               flag = false;
               num1 = num2 & 0xFFFFUL;
               num1 = num1 << 16;
               num1 = num1 + (num2 >> 24);
               num2 = num2 & 0xFF0000UL;
               num2 = num2 >> 8;
               num1 = num1 + num2;
               break;
           case '9':
               if (flag)
                   num2 = password;
               flag = false;
               num1 = ~num2;
               break;
           default: // Impossible if contracts are active.
               assert(0, "Non-digit in nonce");
       }
       num2 = num1;
   }
   return num1 & m_1;

}

void ownTestCalcPass(in string sPassword, in string nonce, in ulong expected) in {

   assert(sPassword.representation.all!isDigit);
   assert(nonce.representation.all!isDigit);

} body {

   immutable password = sPassword.to!ulong;
   immutable res = ownCalcPass(password, nonce);
   immutable m = format("%d %s %d %d", password, nonce, res, expected);
   writeln((res == expected) ? "PASS " : "FAIL ", m);

}

void main() {

   ownTestCalcPass("12345", "603356072", 25280520UL);
   ownTestCalcPass("12345", "410501656", 119537670UL);

}</lang>

Output:
PASS 12345 603356072 25280520 25280520
PASS 12345 410501656 119537670 119537670

JavaScript

<lang javascript> function calcPass (pass, nonce) { var flag = true; var num1 = 0x0; var num2 = 0x0; var password = parseInt(pass, 10);

for (var c in nonce) { c = nonce[c]; if (c!='0') { if (flag) num2 = password; flag = false; } switch (c) { case '1': num1 = num2 & 0xFFFFFF80; num1 = num1 >>> 7; num2 = num2 << 25; num1 = num1 + num2; break; case '2': num1 = num2 & 0xFFFFFFF0; num1 = num1 >>> 4; num2 = num2 << 28; num1 = num1 + num2; break; case '3': num1 = num2 & 0xFFFFFFF8; num1 = num1 >>> 3; num2 = num2 << 29; num1 = num1 + num2; break; case '4': num1 = num2 << 1; num2 = num2 >>> 31; num1 = num1 + num2; break; case '5': num1 = num2 << 5; num2 = num2 >>> 27; num1 = num1 + num2; break; case '6': num1 = num2 << 12; num2 = num2 >>> 20; num1 = num1 + num2; break; case '7': num1 = num2 & 0x0000FF00; num1 = num1 + (( num2 & 0x000000FF ) << 24 ); num1 = num1 + (( num2 & 0x00FF0000 ) >>> 16 ); num2 = ( num2 & 0xFF000000 ) >>> 8; num1 = num1 + num2; break; case '8': num1 = num2 & 0x0000FFFF; num1 = num1 << 16; num1 = num1 + ( num2 >>> 24 ); num2 = num2 & 0x00FF0000; num2 = num2 >>> 8; num1 = num1 + num2; break; case '9': num1 = ~num2; break; case '0': num1 = num2; break; } num2 = num1; } return (num1 >>> 0).toString(); }

exports.calcPass = calcPass;

console.log ('openpass initialization'); function testCalcPass (pass, nonce, expected) { var res = calcPass (pass, nonce); var m = pass + ' ' + nonce + ' ' + res + ' ' + expected; if (res == parseInt(expected, 10)) console.log ('PASS '+m); else console.log ('FAIL '+m); }

testCalcPass ('12345', '603356072', '25280520'); testCalcPass ('12345', '410501656', '119537670'); testCalcPass ('12345', '630292165', '4269684735'); testCalcPass ('12345', '523781130', '537331200'); </lang>

Kotlin

Translation of: Python

<lang scala>// version 1.1.51

fun ownCalcPass(password: Long, nonce: String): Long {

   val m1        = 0xFFFF_FFFFL
   val m8        = 0xFFFF_FFF8L
   val m16       = 0xFFFF_FFF0L
   val m128      = 0xFFFF_FF80L
   val m16777216 = 0xFF00_0000L
   var flag = true
   var num1 = 0L
   var num2 = 0L
   for (c in nonce) {
       num2 = num2 and m1
       when (c) {
           '1' -> {
               if (flag) num2 = password
               flag = false
               num1 = num2 and m128
               num1 = num1 ushr 7
               num2 = num2 shl 25
               num1 = num1 + num2
           }
           '2' -> {
               if (flag) num2 = password
               flag = false
               num1 = num2 and m16
               num1 = num1 ushr 4
               num2 = num2 shl 28
               num1 = num1 + num2
           }
           '3' -> {
               if (flag) num2 = password
               flag = false
               num1 = num2 and m8
               num1 = num1 ushr 3
               num2 = num2 shl 29
               num1 = num1 + num2
           }
           '4' -> {
               if (flag) num2 = password
               flag = false
               num1 = num2 shl 1
               num2 = num2 ushr 31
               num1 = num1 + num2
           }
           '5' -> {
               if (flag) num2 = password
               flag = false
               num1 = num2 shl 5
               num2 = num2 ushr 27
               num1 = num1 + num2
           }
           '6' -> {
               if (flag) num2 = password
               flag = false
               num1 = num2 shl 12
               num2 = num2 ushr 20
               num1 = num1 + num2
           }
           '7' -> {
               if (flag) num2 = password
               flag = false
               num1 = num2 and 0xFF00L
               num1 = num1 + ((num2 and 0xFFL) shl 24)
               num1 = num1 + ((num2 and 0xFF0000L) ushr 16)
               num2 = (num2 and m16777216) ushr 8
               num1 = num1 + num2
           }
           '8' -> {
               if (flag) num2 = password
               flag = false
               num1 = num2 and 0xFFFFL
               num1 = num1 shl 16
               num1 = num1 + (num2 ushr 24)
               num2 = num2 and 0xFF0000L
               num2 = num2 ushr 8
               num1 = num1 + num2
           }
           '9' -> {
               if (flag) num2 = password
               flag = false
               num1 = num2.inv()
           }
           else -> num1 = num2
       }
       num2 = num1
   }
   return num1 and m1

}

fun ownTestCalcPass(passwd: String, nonce: String, expected: Long) {

   val res = ownCalcPass(passwd.toLong(), nonce)
   val m = "$passwd  $nonce  $res  $expected"
   println(if (res == expected) "PASS  $m" else "FAIL  $m")

}

fun main(args: Array<String>) {

   ownTestCalcPass("12345", "603356072", 25280520)
   ownTestCalcPass("12345", "410501656", 119537670)

}</lang>

Output:
PASS  12345  603356072  25280520  25280520
PASS  12345  410501656  119537670  119537670

Python

<lang python>#!/usr/bin/env python

  1. -*- coding: utf-8 -*-

def ownCalcPass (password, nonce) :

   m_1 = 0xFFFFFFFFL
   m_8 = 0xFFFFFFF8L
   m_16 = 0xFFFFFFF0L
   m_128 = 0xFFFFFF80L
   m_16777216 = 0XFF000000L
   flag = True
   num1 = 0L
   num2 = 0L
   password = long(password)
   for c in nonce :
       num1 = num1 & m_1
       num2 = num2 & m_1
       if c == '1':
           length = not flag
           if not length :
               num2 = password
           num1 = num2 & m_128
           num1 = num1 >> 7
           num2 = num2 << 25
           num1 = num1 + num2
           flag = False
       elif c == '2':
           length = not flag
           if not length :
               num2 = password
           num1 = num2 & m_16
           num1 = num1 >> 4
           num2 = num2 << 28
           num1 = num1 + num2
           flag = False
       elif c == '3':
           length = not flag
           if not length :
               num2 = password
           num1 = num2 & m_8
           num1 = num1 >> 3
           num2 = num2 << 29
           num1 = num1 + num2
           flag = False
       elif c == '4':
           length = not flag
           if not length:
               num2 = password
           num1 = num2 << 1
           num2 = num2 >> 31
           num1 = num1 + num2
           flag = False
       elif c == '5':
           length = not flag
           if not length:
               num2 = password
           num1 = num2 << 5
           num2 = num2 >> 27
           num1 = num1 + num2
           flag = False
       elif c == '6':
           length = not flag
           if not length:
               num2 = password
           num1 = num2 << 12
           num2 = num2 >> 20
           num1 = num1 + num2
           flag = False
       elif c == '7':
           length = not flag
           if not length:
               num2 = password
           num1 = num2 & 0xFF00L
           num1 = num1 + (( num2 & 0xFFL ) << 24 )
           num1 = num1 + (( num2 & 0xFF0000L ) >> 16 )
           num2 = ( num2 & m_16777216 ) >> 8
           num1 = num1 + num2
           flag = False
       elif c == '8':
           length = not flag
           if not length:
               num2 = password
           num1 = num2 & 0xFFFFL
           num1 = num1 << 16
           num1 = num1 + ( num2 >> 24 )
           num2 = num2 & 0xFF0000L
           num2 = num2 >> 8
           num1 = num1 + num2
           flag = False
       elif c == '9':
           length = not flag
           if not length:
               num2 = password
           num1 = ~num2
           flag = False
       else :
           num1 = num2
       num2 = num1
   return num1 & m_1

def ownTestCalcPass (passwd, nonce, expected) :

       res = ownCalcPass(passwd, nonce)
       m = passwd+' '+nonce+' '+str(res)+' '+str(expected)
       if res == long(expected) :
               print 'PASS '+m
       else : 
               print 'FAIL '+m

if __name__ == '__main__':

   import sys
   ownTestCalcPass('12345','603356072','25280520')
   ownTestCalcPass('12345','410501656','119537670')

</lang>

PHP

<lang PHP>function ownCalcPass($password, $nonce) {

   $msr = 0x7FFFFFFF;
   $m_1 = (int)0xFFFFFFFF;
   $m_8 = (int)0xFFFFFFF8;
   $m_16 = (int)0xFFFFFFF0;
   $m_128 = (int)0xFFFFFF80;
   $m_16777216 = (int)0xFF000000;
   $flag = True;
   $num1 = 0;
   $num2 = 0;
   foreach (str_split($nonce) as $c) {
       $num1 = $num1 & $m_1;
       $num2 = $num2 & $m_1;
       if ($c == '1') {
           $length = !$flag;
           if (!$length) {
               $num2 = $password;
           }
           $num1 = $num2 & $m_128;
           $num1 = $num1 >> 1;
           $num1 = $num1 & $msr;
           $num1 = $num1 >> 6;
           $num2 = $num2 << 25;
           $num1 = $num1 + $num2;
           $flag = False;
       } elseif ($c == '2') {
           $length = !$flag;
           if (!$length) {
               $num2 = $password;
           }
           $num1 = $num2 & $m_16;
           $num1 = $num1 >> 1;
           $num1 = $num1 & $msr;
           $num1 = $num1 >> 3;
           $num2 = $num2 << 28;
           $num1 = $num1 + $num2;
           $flag = False;
       } elseif ($c == '3') {
           $length = !$flag;
           if (!$length) {
               $num2 = $password;
           }
           $num1 = $num2 & $m_8;
           $num1 = $num1 >> 1;
           $num1 = $num1 & $msr;
           $num1 = $num1 >> 2;
           $num2 = $num2 << 29;
           $num1 = $num1 + $num2;
           $flag = False;
       } elseif ($c == '4') {
           $length = !$flag;
           if (!$length) {
               $num2 = $password;
           }
           $num1 = $num2 << 1;
           $num2 = $num2 >> 1;
           $num2 = $num2 & $msr;
           $num2 = $num2 >> 30;
           $num1 = $num1 + $num2;
           $flag = False;
       } elseif ($c == '5') {
           $length = !$flag;
           if (!$length) {
               $num2 = $password;
           }
           $num1 = $num2 << 5;
           $num2 = $num2 >> 1;
           $num2 = $num2 & $msr;
           $num2 = $num2 >> 26;
           $num1 = $num1 + $num2;
           $flag = False;
       } elseif ($c == '6') {
           $length = !$flag;
           if (!$length) {
               $num2 = $password;
           }
           $num1 = $num2 << 12;
           $num2 = $num2 >> 1;
           $num2 = $num2 & $msr;
           $num2 = $num2 >> 19;
           $num1 = $num1 + $num2;
           $flag = False;
       } elseif ($c == '7') {
           $length = !$flag;
           if (!$length) {
               $num2 = $password;
           }
           $num1 = $num2 & 0xFF00;
           $num1 = $num1 + (( $num2 & 0xFF ) << 24 );
           $num1 = $num1 + (( $num2 & 0xFF0000 ) >> 16 );
           $num2 = $num2 & $m_16777216;
           $num2 = $num2 >> 1;
           $num2 = $num2 & $msr;
           $num2 = $num2 >> 7;
           $num1 = $num1 + $num2;
           $flag = False;
       } elseif ($c == '8') {
           $length = !$flag;
           if (!$length) {
               $num2 = $password;
           }
           $num1 = $num2 & 0xFFFF;
           $num1 = $num1 << 16;
           $numx = $num2 >> 1;
           $numx = $numx & $msr;
           $numx = $numx >> 23;
           $num1 = $num1 + $numx;
           $num2 = $num2 & 0xFF0000;
           $num2 = $num2 >> 1;
           $num2 = $num2 & $msr;
           $num2 = $num2 >> 7;
           $num1 = $num1 + $num2;
           $flag = False;
       } elseif ($c == '9') {
           $length = !$flag;
           if (!$length) {
               $num2 = $password;
           }
           $num1 = ~(int)$num2;
           $flag = False;
       } else {
           $num1 = $num2;
       }
       $num2 = $num1;
   }
   return sprintf('%u', $num1 & $m_1);

} </lang>

Racket

Translation of: Python

(sort of)

<lang racket> </lang>