OpenWebNet Password

From Rosetta Code
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[edit]

Translation of: Python
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);
}
Output:
PASS 12345 603356072 25280520 25280520
PASS 12345 410501656 119537670 119537670

JavaScript[edit]

 
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');
 

Python[edit]

#!/usr/bin/env python
# -*- 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')
 

PHP[edit]

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);
}