Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No encryption during provisioning? #648

Open
Lull3n opened this issue Jan 18, 2022 · 15 comments
Open

No encryption during provisioning? #648

Lull3n opened this issue Jan 18, 2022 · 15 comments

Comments

@Lull3n
Copy link

Lull3n commented Jan 18, 2022

Was looking to implement the provisioning directly on android, and had a look at the setup method. Am i misunderstanding something here or are my wifi creds sent in unicode over open wifi?

Edit: typo

@felipediel
Copy link
Collaborator

It's not open Wi-Fi, you need to connect to the Wi-Fi network that your Broadlink device generates in AP setup mode.

@Lull3n
Copy link
Author

Lull3n commented Jan 25, 2022

Hmm, might be that I've misunderstood wifi principles here, but aren't WiFi's with no password unencrypted?

@felipediel
Copy link
Collaborator

It is a private network to which you only connect a single time with a single device. It's not like broadcasting your credentials on your main network, that's what I mean.

@Lull3n
Copy link
Author

Lull3n commented Jan 25, 2022

I feel I'm probably misunderstanding here? What I mean is if the wifi is not protected, it's not encrypted? And if there is no application layer encryption anyone sniffing the radio will then be able to read my wifi creds? I had a look at the JS in the "wifi login page" generated by my bulb, and it applies what appears to (to my untrained JS eyes) application layer encryption, which seems to support my suspections somewhat.

@felipediel
Copy link
Collaborator

It uses WPS, the communication is encrypted.

@Lull3n
Copy link
Author

Lull3n commented Jan 25, 2022

I fear my broadlink "Smart Bulb" doesent. There are no buttons on the bulb, no PIN requests, and netsh reports:
Network type : Infrastructure Radio type : 802.11n Authentication : Open Cipher : None

@felipediel
Copy link
Collaborator

Sometimes it's not a button, but a specific way you turn the power on and off to put it in AP setup mode. I don't have the bulb, I don't know how it works exactly, but the configuration is probably similar to the other devices with Broadlink DNA.

@Lull3n
Copy link
Author

Lull3n commented Jan 25, 2022

Fair, i guess if there is WPS the device should only accept one concurrent connection? Otherwise the whole point of encrypting the data would be lost as anyone could just obtain the keys. I can connect multiple devices to the AP at the same time, and anyways as stated windows reports the connection as unencrypted. So, im getting fairly confident that the wifi creds are actually being broadcast unencrypted. Seing as broadlink has mitigated this with application level encryption i think you should look in to this, or at the very least disable the setup method for connections that have no encryption. I can take a swing at sniffing the packets if you need me to, and i can upload the JS encryption functions used by broadlink if you want to, but im afraid i can't make any PR's as my python is horrible.

@felipediel
Copy link
Collaborator

felipediel commented Mar 19, 2022

When we connect via WPS, the Broadlink device restricts the connection to the client and the Wi-Fi configuration is done with encryption. WPS is like connecting with passwords, but we press a button to grant permission to the first device that connects.

@Lull3n
Copy link
Author

Lull3n commented Mar 19, 2022

I'm well aware what wps is, as stated there is no WPS in my lb2 (can get you the hex code if you want) the encryption is instead done in the application layer using a rabbit cipher that's run in JS on the the phone/tablet used for provisioning. As I've also already stated windows also reports the connection as unencrypted hence any credentials sent on the network without adding application layer encryption are subject to sniffing, and the only security granted here is by obscurity.

@Lull3n
Copy link
Author

Lull3n commented Mar 19, 2022

Really cool project, and super greatful for all the work ofc, but you should at least inform your users that the credentials are sent in cleartext instead of just saying there's WPS (which there at least isn't on my device) and closing the issue.

@felipediel
Copy link
Collaborator

felipediel commented Mar 19, 2022

Okay, sorry, I'm short on time for the project so I end up having to make choices. I'll leave it open a little longer in case anyone wants to improve this with a PR. Thanks for reporting.

@felipediel felipediel reopened this Mar 19, 2022
@felipediel
Copy link
Collaborator

If you could paste that Js here, it would be of great help.

@Lull3n
Copy link
Author

Lull3n commented Mar 21, 2022

No worries mate! Sure! The bulbs i have are LB27-R1 mentioned in #522 sorry about confusing it with LB2. When provisioning the bulb send a page with some gnarly ass JS. I guess the actual encryption takes place in "_rabbit" but there's also a lot of stuff generating keys and such.

var cou = "Deutschland", la = "en-us", n = "001", hd = "device-heartbeat-deu-6dc239d5.ibroadlink.com", gd = "device-gateway-deu-6dc239d5.ibroadlink.com", rg = "Europe", ac = "Europe", r_f_ = 1, lan = [ "Select Wi-Fi network", "Input Wi-Fi password", "OK", "Input ", " ", "phone", "", "Close", "email", "", "Format error", "SMS", "Select the router to which the device will be connected (only 2.4GHz)", "", " to the router", "1. After the device is online, a confirmation [s] will be sent to {s}.", "3. If you do not receive the email in 5min, please check your span in email. ", "Tap ''Connect now'' to connect the device", "The device is connecting ", "Device configuration timed out. Please make sure the information filled in is correct.", "OK", "2. Search and enable “BroadLink” skill/service in Alexa or Google Home app, then sign in with [s] use the skill. ", "Please close this page if you have received the confirmation [s].", "", "Internet connection issue on router.", "Back", "Connect now", "I have read the above information", "", "", "Use [s] to activate your device", "Input your [s] to sign up", "", "", "", "", "", "OK", "", "V1.3.3", "This page might be closed automatically after the device is successfully connected to the router.", "Next", "Loading", "email", "1. After the device is online, a confirmation email will be sent to %1s.", "2. Search and enable ''BroadLink'' skill/service in Alexa or Google Home app, then sign in with %1s use the skill.", "3. If you do not receive the email in 5min, please check your spam in email.", "Sign in with [s] if you already have BroadLink account", "", "", "What is name of your device?", "Enter the name of your device", "Enter the [s] name", "The name cannot contain special characters", "Device name exists", "4. If you still cannot find the email in your spam folder, that means your device is failed to connect to Internet. Please check your network connection and Wi-Fi password. Reset the device following instructions in the product manual and try again.", ]; var d_nam = "Color Bulb"; var vGroups = []; g1 = ""; itr = [ ]; var p_k, t_132, s_k; wfl = []; iv = null; lte = ld = 1; clr = window.getComputedStyle($("bgc"), null).backgroundColor; d_d = "disabled"; p = "placeholder"; bgd = "background"; dy_ = "display"; cd_ = "checked"; s_r = ""; s_r1 = ""; ve = "value"; s1 = "onfocus"; s2 = "this.blur()"; s3 = "readonly"; pwd = 1; if (r_f_ === 1) { r("em_"); } else { r("ph_"); } sa("dev_name", ve, d_nam); sa("dev_name", 0, "n"); sa("p_b3", 0, "n"); function f_ng(h) { return new Uint8Array( h.match(/.{1,2}/g).map(function (byte) { return parseInt(byte, 16); }) ); } function t_ng(b) { return b.reduce(function (str, byte) { return str + p_rt(byte.toString(16)); }, ""); } function p_rt(r) { var r1 = r.length, r2; if (r1 == 0) { r2 = "00"; } else if (r1 == 1) { r2 = "0" + r; } else { r2 = r; } return r2; } function block_(n) { a_r(n, dy_, "block"); } function none_(n) { a_r(n, dy_, "none"); } function r_write() { a_r("bl", bgd, "#bfbfbf"); no1("simg"); sa("bg", 0, "n"); } function no1(v) { a_r("bl", bgd, "#bfbfbf"); sa(v, "src", itr[0]); r(v); } function dev_inp(e) { var pattern = /[!@#$%^&*€£()_-+=<>?:{}|,./;'\\[]·!@#¥%&*()-+={}|《》?:“”【】、;‘’,。、‘•‘]/im;
var pattern1 = /[……——]/im;
var v = $("dev_name")[ve];
if (v && (pattern.test(v) || pattern1.test(v))) {
ih("err", lan[53]);
r("err");
a_r("bc", bgd, "#bfbfbf");
return;
} else {
ih("err", "0");
sa("err", "class", "n_");
}
c_inp();
}
function hc() {
sa("cd", 0, "n");
sa("ci", 0, "");
r("ic");
clearInterval(t_132);
if (typeof t_fn == "number") {
clearInterval(t_fn);
t_fn = undefined;
}
}
function c_() {
block_("s_n");
block_("b_b");
block_("v1");
block_("snf");
s = tm("s");
p = tm("p");
ph = tm("ph");
em = tm("em_info");
var j = $("bc").style[bgd];
if (j == "" || j == "rgb(191, 191, 191)" || j == "#bfbfbf") {
return;
}
ih("err", "0");
sa("err", 0, "n_");
if (r_f_ == 1) {
s_r = j1(2);
s_r1 = j1(4);
if (em.indexOf("@") < 0) {
ih(0, lan[10]);
return;
}
}
if (r_f_ == 2) {
s_r = j1(3);
s_r1 = j1(3);
if (!ph) {
return;
}
}
r("bg");
ih("c1", lan[17] + lan[14]);
ih("c4", lan[55]);
var s1 = "",
s2 = "
";
if (r_f_ == 1) {
ih("c3", lan[16]);
ih("c2", lan[15].replace("{s}", s1 + em + s2).replace("[s]", lan[8]));
ih("c_1", lan[21].replace("[s]", s1 + em + s2));
}
if (r_f_ == 2) {
ih("c3", lan[46]);
ih("c2", lan[44].replace("{s}", s1 + ph + s2).replace("[s]", lan[5]));
ih("c_1", lan[45].replace("[s]", s1 + ph + s2));
}
block_("c2");
block_("c3");
block_("c4");
}
function j1(a) {
var o1 = "";
if (a == 1) {
o1 = lan[5];
}
if (a == 2) {
o1 = lan[8];
}
if (a == 3) {
o1 = lan[11];
}
if (a == 4) {
o1 = lan[43];
}
return o1;
}
function real_click() {
if ($("simg").className) {
ih("cdt", lan[40]);
ih("ct4", lan[37]);
sa("ct4", "onclick", "ctn(event,1)");
r("ct");
}
}
function l1(a2, b2) {
return lan[a2].replace(/[s]/g, b2);
}
function cn() {
ih("c1", lan[18] + lan[14] + "……");
var obj = {
s: s,
p: p,
lan: la,
q: n,
hd: hd,
gd: gd,
country: cou,
ac: ac,
rg: rg,
devinfo: blrabbit.base64Encode(
JSON.stringify({ dn: d_nam, rn: "Living Room", group: { vGroups } })
),
lock: 1,
};
if (r_f_ == 1) {
obj.em = em;
}
if (r_f_ == 2) {
obj.ph = ph;
}
console.log({ dn: d_nam, rn: "Living Room", group: { vGroups } });
console.log(obj);
ht(
"pubkey",
0,
function (d) {
if (d.code == 0) {
var seed = axlsign.generateKeyPair(new Uint8Array(32));
p_k = t_ng(seed.public);
s_k = axlsign.sharedKey(seed.private, f_ng(d.pubkey));
ht("wifiset", {
pubkey: p_k,
data: blrabbit.encrypt_(JSON.stringify(obj), s_k),
});
}
},
"GET"
);
setTimeout(function () {
r("ct");
ih("cdt", lan[19]);
ih("ct4", lan[20]);
sa("ct4", "onclick", "ctn(event)");
}, 300000);
}
function r(s, a) {
$(s || "bc").removeAttribute(a || "class");
}
function ht(p, d, c, t) {
var x = new XMLHttpRequest();
x.onreadystatechange = function () {
if (x.readyState == 4 && x.status == 200) {
ld = 1;
r();
r("ic");
sa("lt", 0, "cb");
c ? c(JSON.parse(x.responseText)) : 0;
}
};
x.open(t || "POST", "/" + p);
x.setRequestHeader("Content-type", "application/json;charset=UTF-8");
x.send(JSON.stringify(d));
}
function cs(s, k) {
var v = "";
sa("s", s3, s3);
sa("s", s1, s2);
v = s;
if (!k) {
sa("sp", 0, "n");
sv("p");
} else {
r("sp");
}
sv("s", v);
c_inp();
hc();
}
function ss(d) {
sa(d || "cd", 0, "d");
}
function gw(e) {
pe(e);
if ($("ci").className == "k") {
hc();
sa("ci", 0, "");
r("ic");
} else {
sa("ci", 0, "k");
g_w();
}
}
function g_w() {
if (typeof t_fn != "number") {
t_fn = setInterval(function () {
g_w();
}, 30000);
}
ht(
"wifiget",
0,
function (d) {
ss();
sa("ic", 0, "l__");
var t = d.list || [];
t.unshift({ s: lan[42], n: "998" });
wfl = t;
x_(t, "sb", "css");
ing();
},
"get"
);
}
function x_(b, c, e) {
var s = "",
s_9 = "

";
for (var i = 0; i < b.length; i++) {
var a = b[i];
if (a.n == "998") {
s +=
"

" +
a.s +
"." +
s_9;
} else {
s +=
"<p onclick=" +
e +
"(" +
i +
")>" +
a.s +
"
" +
(a.e >= 0 ? (a.e ? "password" : "open") : "") +
s_9;
}
}
ih(c, s);
$(c).scrollTop = 0;
}
function $(k) {
return document.getElementById(k);
}
function sa(i, a, m) {
$(i).setAttribute(a || "class", m);
}
function ck() {
c_inp();
sv("ph", tm("ph").substr(0, 20));
}
function ih(d, m) {
$(d || "lt").innerHTML = m;
!d &&
setTimeout(function () {
ih("lt", "");
}, 3000);
}
function pe(e, p) {
!p && e.preventDefault();
e.stopPropagation();
}
function tm(d) {
return $(d)[ve].trim();
}
function tl(d) {
($(d) || document).addEventListener(
"touchmove",
function (e) {
pe(e, !d || d == "sb" || d == "m" || d == "idtc");
},
{ passive: false }
);
}
function ctn(e, k) {
pe(e);
sa("ct", 0, "n");
none_("v1");
none_("snf");
if (k == 1) {
none_("c2");
none_("c3");
none_("c4");
none_("b_b");
none_("s_n");
ih("c_1", l1(22, s_r1));
cn();
} else {
r_write();
sa("p", "type", "text");
r("img");
}
}
function hcd(e) {
pe(e);
sa("cd", 0, "n");
}
function css(i) {
sv("p");
var t = wfl[i] || {};
pwd = t.e;
cs(t.s, t.e);
hc();
}
function stp_(n, e) {
pe(e);
var v = n == 1 ? "img" : "simg";
if (n == 2) {
if ($(v).className == "y1") {
no1(v);
} else {
a_r("bl", bgd, clr);
sa(v, "src", itr[1]);
sa(v, 0, "y1");
}
} else {
if ($(v).className == "fi") {
r(v);
sa("p", "type", "text");
} else {
sa("p", "type", "password");
sa(v, 0, "fi");
}
}
}
function sv(d, v) {
$(d)[ve] = v || "";
}
function ing() {
var l_ = 1;
t_132 = setInterval(function () {
l_++;
if (l_ % 3 === 1) {
i1("i_", ".");
}
if (l_ % 3 === 2) {
i1("i_", "..");
}
if (l_ % 3 === 0) {
i1("i_", "...");
}
}, 500);
}
function i1(a3, b3) {
$(a3).innerText = b3;
}
function a_r(n, a, r) {
$(n).style[a] = r;
}
function c_inp() {
a_r("bc", bgd, "#bfbfbf");
if (tm("s") == "" || tm("dev_name") == "") {
return;
}
if (r_f_ == 1 && tm("em_info") == "") {
return;
}
if (r_f_ == 2 && tm("ph") == "") {
return;
}
a_r("bc", bgd, clr);
}
window.onload = function () {
var d = document.documentElement || document.body;
d.style.fontSize = d.clientWidth / 7.5 + "px";
ih("bc", lan[41]);
ih("p_b1", lan[47].replace("[s]", r_f_ === 1 ? lan[8] : lan[5]));
sa("s", p, lan[0]);
sa("p", p, lan[1]);
sa("ph", p, l1(31, r_f_ == 1 ? lan[8] : lan[5]));
sa("em_info", p, l1(31, r_f_ == 1 ? lan[8] : lan[5]));
sa("dev_name", p, lan[51]);
sa("s", s3, s3);
sa("s", s1, s2);
var o1 = ["tp", "s_n", "bl", "v", "v1", "p_b3"],
o2 = [12, 25, 26, 39, 39, 50];
ih("p_b", l1(30, r_f_ == 1 ? lan[8] : lan[5]));
ih("ik", "" + lan[27]);
for (var p_ = 0; p_ < o1.length; p_++) {
ih(o1[p_], lan[o2[p_]]);
}
tl("sb");
tl("m");
tl();
tl("cd");
tl("idtc");
};

(function (axlsign) {
var gf = function (init) {
var i,
r = new Float64Array(16);
if (init) for (i = 0; i < init.length; i++) r[i] = init[i];
return r;
};
var _9 = new Uint8Array(32);
_9[0] = 9;
var _121665 = gf([0xdb41, 1]);
function car25519(o) {
var i,
v,
c = 1;
for (i = 0; i < 16; i++) {
v = o[i] + c + 65535;
c = Math.floor(v / 65536);
o[i] = v - c * 65536;
}
o[0] += c - 1 + 37 * (c - 1);
}
function sel25519(p, q, b) {
var t,
c = ~(b - 1);
for (var i = 0; i < 16; i++) {
t = c & (p[i] ^ q[i]);
p[i] ^= t;
q[i] ^= t;
}
}
function pack25519(o, n) {
var i, j, b;
var m = gf(),
t = gf();
for (i = 0; i < 16; i++) t[i] = n[i];
car25519(t);
car25519(t);
car25519(t);
for (j = 0; j < 2; j++) {
m[0] = t[0] - 0xffed;
for (i = 1; i < 15; i++) {
m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
m[i - 1] &= 0xffff;
}
m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
b = (m[15] >> 16) & 1;
m[14] &= 0xffff;
sel25519(t, m, 1 - b);
}
for (i = 0; i < 16; i++) {
o[2 * i] = t[i] & 0xff;
o[2 * i + 1] = t[i] >> 8;
}
}
function unpack25519(o, n) {
var i;
for (i = 0; i < 16; i++) o[i] = n[2 * i] + (n[2 * i + 1] << 8);
o[15] &= 0x7fff;
}
function A(o, a, b) {
for (var i = 0; i < 16; i++) o[i] = a[i] + b[i];
}
function Z(o, a, b) {
for (var i = 0; i < 16; i++) o[i] = a[i] - b[i];
}
function M(o, a, b) {
v,
c,
(t0 = 0),
(t1 = 0),
(t2 = 0),
(t3 = 0),
(t4 = 0),
(t5 = 0),
(t6 = 0),
(t7 = 0),
(t8 = 0),
(t9 = 0),
(t10 = 0),
(t11 = 0),
(t12 = 0),
(t13 = 0),
(t14 = 0),
(t15 = 0),
(t16 = 0),
(t17 = 0),
(t18 = 0),
(t19 = 0),
(t20 = 0),
(t21 = 0),
(t22 = 0),
(t23 = 0),
(t24 = 0),
(t25 = 0),
(t26 = 0),
(t27 = 0),
(t28 = 0),
(t29 = 0),
(t30 = 0),
(b0 = b[0]),
(b1 = b[1]),
(b2 = b[2]),
(b3 = b[3]),
(b4 = b[4]),
(b5 = b[5]),
(b6 = b[6]),
(b7 = b[7]),
(b8 = b[8]),
(b9 = b[9]),
(b10 = b[10]),
(b11 = b[11]),
(b12 = b[12]),
(b13 = b[13]),
(b14 = b[14]),
(b15 = b[15]);
var p = 0;
for (var i1 = 0; i1 <= 15; i1++) {
v = a[i1];
for (var j1 = i1; j1 <= i1 + 15; j1++) {
window["t" + j1] += v * window["b" + p];
if (j1 >= i1 + 15) {
p = 0;
} else {
p++;
}
}
}
t0 += 38 * t16;
t1 += 38 * t17;
t2 += 38 * t18;
t3 += 38 * t19;
t4 += 38 * t20;
t5 += 38 * t21;
t6 += 38 * t22;
t7 += 38 * t23;
t8 += 38 * t24;
t9 += 38 * t25;
t10 += 38 * t26;
t11 += 38 * t27;
t12 += 38 * t28;
t13 += 38 * t29;
t14 += 38 * t30;
c = 1;
v = t0 + c + 65535;
c = Math.floor(v / 65536);
t0 = v - c * 65536;
v = t1 + c + 65535;
c = Math.floor(v / 65536);
t1 = v - c * 65536;
v = t2 + c + 65535;
c = Math.floor(v / 65536);
t2 = v - c * 65536;
v = t3 + c + 65535;
c = Math.floor(v / 65536);
t3 = v - c * 65536;
v = t4 + c + 65535;
c = Math.floor(v / 65536);
t4 = v - c * 65536;
v = t5 + c + 65535;
c = Math.floor(v / 65536);
t5 = v - c * 65536;
v = t6 + c + 65535;
c = Math.floor(v / 65536);
t6 = v - c * 65536;
v = t7 + c + 65535;
c = Math.floor(v / 65536);
t7 = v - c * 65536;
v = t8 + c + 65535;
c = Math.floor(v / 65536);
t8 = v - c * 65536;
v = t9 + c + 65535;
c = Math.floor(v / 65536);
t9 = v - c * 65536;
v = t10 + c + 65535;
c = Math.floor(v / 65536);
t10 = v - c * 65536;
v = t11 + c + 65535;
c = Math.floor(v / 65536);
t11 = v - c * 65536;
v = t12 + c + 65535;
c = Math.floor(v / 65536);
t12 = v - c * 65536;
v = t13 + c + 65535;
c = Math.floor(v / 65536);
t13 = v - c * 65536;
v = t14 + c + 65535;
c = Math.floor(v / 65536);
t14 = v - c * 65536;
v = t15 + c + 65535;
c = Math.floor(v / 65536);
t15 = v - c * 65536;
t0 += c - 1 + 37 * (c - 1);
c = 1;
v = t0 + c + 65535;
c = Math.floor(v / 65536);
t0 = v - c * 65536;
v = t1 + c + 65535;
c = Math.floor(v / 65536);
t1 = v - c * 65536;
v = t2 + c + 65535;
c = Math.floor(v / 65536);
t2 = v - c * 65536;
v = t3 + c + 65535;
c = Math.floor(v / 65536);
t3 = v - c * 65536;
v = t4 + c + 65535;
c = Math.floor(v / 65536);
t4 = v - c * 65536;
v = t5 + c + 65535;
c = Math.floor(v / 65536);
t5 = v - c * 65536;
v = t6 + c + 65535;
c = Math.floor(v / 65536);
t6 = v - c * 65536;
v = t7 + c + 65535;
c = Math.floor(v / 65536);
t7 = v - c * 65536;
v = t8 + c + 65535;
c = Math.floor(v / 65536);
t8 = v - c * 65536;
v = t9 + c + 65535;
c = Math.floor(v / 65536);
t9 = v - c * 65536;
v = t10 + c + 65535;
c = Math.floor(v / 65536);
t10 = v - c * 65536;
v = t11 + c + 65535;
c = Math.floor(v / 65536);
t11 = v - c * 65536;
v = t12 + c + 65535;
c = Math.floor(v / 65536);
t12 = v - c * 65536;
v = t13 + c + 65535;
c = Math.floor(v / 65536);
t13 = v - c * 65536;
v = t14 + c + 65535;
c = Math.floor(v / 65536);
t14 = v - c * 65536;
v = t15 + c + 65535;
c = Math.floor(v / 65536);
t15 = v - c * 65536;
t0 += c - 1 + 37 * (c - 1);
o[0] = t0;
o[1] = t1;
o[2] = t2;
o[3] = t3;
o[4] = t4;
o[5] = t5;
o[6] = t6;
o[7] = t7;
o[8] = t8;
o[9] = t9;
o[10] = t10;
o[11] = t11;
o[12] = t12;
o[13] = t13;
o[14] = t14;
o[15] = t15;
}
function S(o, a) {
M(o, a, a);
}
function inv25519(o, i) {
var c = gf();
var a;
for (a = 0; a < 16; a++) c[a] = i[a];
for (a = 253; a >= 0; a--) {
S(c, c);
if (a !== 2 && a !== 4) M(c, c, i);
}
for (a = 0; a < 16; a++) o[a] = c[a];
}
function crypto_scalarmult(q, n, p) {
var z = new Uint8Array(32);
var x = new Float64Array(80),
r,
i;
var a = gf(),
b = gf(),
c = gf(),
d = gf(),
e = gf(),
f = gf();
for (i = 0; i < 31; i++) z[i] = n[i];
z[31] = (n[31] & 127) | 64;
z[0] &= 248;
unpack25519(x, p);
for (i = 0; i < 16; i++) {
b[i] = x[i];
d[i] = a[i] = c[i] = 0;
}
a[0] = d[0] = 1;
for (i = 254; i >= 0; --i) {
r = (z[i >>> 3] >>> (i & 7)) & 1;
sel25519(a, b, r);
sel25519(c, d, r);
A(e, a, c);
Z(a, a, c);
A(c, b, d);
Z(b, b, d);
S(d, e);
S(f, a);
M(a, c, a);
M(c, b, e);
A(e, a, c);
Z(a, a, c);
S(b, a);
Z(c, d, f);
M(a, c, _121665);
A(a, a, d);
M(c, c, a);
M(a, d, f);
M(d, b, x);
S(b, e);
sel25519(a, b, r);
sel25519(c, d, r);
}
for (i = 0; i < 16; i++) {
x[i + 16] = a[i];
x[i + 32] = c[i];
x[i + 48] = b[i];
x[i + 64] = d[i];
}
var x32 = x.subarray(32);
var x16 = x.subarray(16);
inv25519(x32, x32);
M(x16, x16, x32);
pack25519(q, x16);
return 0;
}
function crypto_scalarmult_base(q, n) {
return crypto_scalarmult(q, n, _9);
}
function checkArrayTypes() {
var t, i;
for (i = 0; i < arguments.length; i++) {
if (
(t = Object.prototype.toString.call(arguments[i])) !==
"[object Uint8Array]"
)
throw new TypeError("unexpected type " + t + ", use Uint8Array");
}
}
axlsign.sharedKey = function (secretKey, publicKey) {
checkArrayTypes(publicKey, secretKey);
if (publicKey.length !== 32) throw new Error("wrong public key length");
if (secretKey.length !== 32) throw new Error("wrong secret key length");
var sharedKey = new Uint8Array(32);
crypto_scalarmult(sharedKey, secretKey, publicKey);
return sharedKey;
};
axlsign.generateKeyPair = function (seed) {
checkArrayTypes(seed);
if (seed.length !== 32) throw new Error("wrong seed length");
var sk = new Uint8Array(32);
var pk = new Uint8Array(32);
for (var i = 0; i < 32; i++) sk[i] = seed[i];
crypto_scalarmult_base(pk, sk);
sk[0] &= 248;
sk[31] &= 127;
sk[31] |= 64;
pk[31] &= 127;
return { public: pk, private: sk };
};
})(
typeof module !== "undefined" && module.exports
? module.exports
: (self.axlsign = self.axlsign || {})
);

(function (blrabbit) {
var x = [],
c = [],
b;
var littleEndian = (function () {
var buffer = new ArrayBuffer(2);
new DataView(buffer).setInt16(0, 256, true);
return new Int16Array(buffer)[0] === 256;
})();
var Util = {
stringToBytes: function (str) {
var bytes = new Array();
var len, c;
len = str.length;
for (var i = 0; i < len; i++) {
c = str.charCodeAt(i);
if (c >= 0x010000 && c <= 0x10ffff) {
bytes.push(((c >> 18) & 0x07) | 0xf0);
bytes.push(((c >> 12) & 0x3f) | 0x80);
bytes.push(((c >> 6) & 0x3f) | 0x80);
bytes.push((c & 0x3f) | 0x80);
} else if (c >= 0x000800 && c <= 0x00ffff) {
bytes.push(((c >> 12) & 0x0f) | 0xe0);
bytes.push(((c >> 6) & 0x3f) | 0x80);
bytes.push((c & 0x3f) | 0x80);
} else if (c >= 0x000080 && c <= 0x0007ff) {
bytes.push(((c >> 6) & 0x1f) | 0xc0);
bytes.push((c & 0x3f) | 0x80);
} else {
bytes.push(c & 0xff);
}
}
return bytes;
},
bytesToString: function (arr) {
if (typeof arr === "string") {
return arr;
}
var str = "",
_arr = arr;
for (var i = 0; i < _arr.length; i++) {
var one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if (v && one.length == 8) {
var bytesLength = v[0].length;
var store = _arr[i].toString(2).slice(7 - bytesLength);
for (var st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2);
}
str += String.fromCharCode(parseInt(store, 2));
i += bytesLength - 1;
} else {
str += String.fromCharCode(arr[i]);
}
}
return str;
},
base64encode: function (buffer) {
var binary = "";
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
},
base64decode: function (base64String) {
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding)
.replace(/-/g, "+")
.replace(/
/g, "/");
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return Array.from(outputArray);
},
rotl: function (k, rot) {
return (k << rot) | (k >>> (32 - rot));
},
};
var Rabbit = {
base64Encode: function (message) {
var m = Util.stringToBytes(message);
return Util.base64encode(m);
},
encrypt: function (message, password) {
var m = Util.stringToBytes(message),
k = [];
var dv = new DataView(password.buffer);
k[0] = dv.getUint32(0, littleEndian);
k[1] = dv.getUint32(4, littleEndian);
k[2] = dv.getUint32(8, littleEndian);
k[3] = dv.getUint32(12, littleEndian);
Rabbit._rabbit(m, k, null);
return Util.base64encode(m);
},
decrypt: function (ciphertext, password) {
var c = Util.base64decode(ciphertext),
k = [];
var dv = new DataView(password.buffer);
k[0] = dv.getUint32(0, littleEndian);
k[1] = dv.getUint32(4, littleEndian);
k[2] = dv.getUint32(8, littleEndian);
k[3] = dv.getUint32(12, littleEndian);
Rabbit._rabbit(c, k, null);
return Util.bytesToString(c);
},
_rabbit: function (m, k, iv) {
Rabbit._keysetup(k);
if (iv) Rabbit._ivsetup(iv);
for (var s = [], i = 0; i < m.length; i++) {
if (i % 16 == 0) {
Rabbit._nextstate();
s[0] = x[0] ^ (x[5] >>> 16) ^ (x[3] << 16);
s[1] = x[2] ^ (x[7] >>> 16) ^ (x[5] << 16);
s[2] = x[4] ^ (x[1] >>> 16) ^ (x[7] << 16);
s[3] = x[6] ^ (x[3] >>> 16) ^ (x[1] << 16);
for (var j = 0; j < 4; j++) {
s[j] =
(((s[j] << 8) | (s[j] >>> 24)) & 0x00ff00ff) |
(((s[j] << 24) | (s[j] >>> 8)) & 0xff00ff00);
}
for (var b = 120; b >= 0; b -= 8)
s[b / 8] = (s[b >>> 5] >>> (24 - (b % 32))) & 0xff;
}
m[i] ^= s[i % 16];
}
},
_keysetup: function (k) {
x[0] = k[0];
x[2] = k[1];
x[4] = k[2];
x[6] = k[3];
x[1] = (k[3] << 16) | (k[2] >>> 16);
x[3] = (k[0] << 16) | (k[3] >>> 16);
x[5] = (k[1] << 16) | (k[0] >>> 16);
x[7] = (k[2] << 16) | (k[1] >>> 16);
c[0] = Util.rotl(k[2], 16);
c[2] = Util.rotl(k[3], 16);
c[4] = Util.rotl(k[0], 16);
c[6] = Util.rotl(k[1], 16);
c[1] = (k[0] & 0xffff0000) | (k[1] & 0xffff);
c[3] = (k[1] & 0xffff0000) | (k[2] & 0xffff);
c[5] = (k[2] & 0xffff0000) | (k[3] & 0xffff);
c[7] = (k[3] & 0xffff0000) | (k[0] & 0xffff);
b = 0;
for (var i = 0; i < 4; i++) Rabbit._nextstate();
for (var i = 0; i < 8; i++) c[i] ^= x[(i + 4) & 7];
},
ivsetup: function (iv) {},
nextstate: function () {
for (var c_old = [], i = 0; i < 8; i++) c_old[i] = c[i];
c[0] = (c[0] + 0x4d34d34d + b) >>> 0;
c[1] = (c[1] + 0xd34d34d3 + (c[0] >>> 0 < c_old[0] >>> 0 ? 1 : 0)) >>> 0;
c[2] = (c[2] + 0x34d34d34 + (c[1] >>> 0 < c_old[1] >>> 0 ? 1 : 0)) >>> 0;
c[3] = (c[3] + 0x4d34d34d + (c[2] >>> 0 < c_old[2] >>> 0 ? 1 : 0)) >>> 0;
c[4] = (c[4] + 0xd34d34d3 + (c[3] >>> 0 < c_old[3] >>> 0 ? 1 : 0)) >>> 0;
c[5] = (c[5] + 0x34d34d34 + (c[4] >>> 0 < c_old[4] >>> 0 ? 1 : 0)) >>> 0;
c[6] = (c[6] + 0x4d34d34d + (c[5] >>> 0 < c_old[5] >>> 0 ? 1 : 0)) >>> 0;
c[7] = (c[7] + 0xd34d34d3 + (c[6] >>> 0 < c_old[6] >>> 0 ? 1 : 0)) >>> 0;
b = c[7] >>> 0 < c_old[7] >>> 0 ? 1 : 0;
for (var g = [], i = 0; i < 8; i++) {
var gx = (x[i] + c[i]) >>> 0;
var ga = gx & 0xffff,
gb = gx >>> 16;
var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb,
gl =
((((gx & 0xffff0000) * gx) >>> 0) +
(((gx & 0x0000ffff) * gx) >>> 0)) >>>
0;
g[i] = gh ^ gl;
}
x[0] =
g[0] + ((g[7] << 16) | (g[7] >>> 16)) + ((g[6] << 16) | (g[6] >>> 16));
x[1] = g[1] + ((g[0] << 8) | (g[0] >>> 24)) + g[7];
x[2] =
g[2] + ((g[1] << 16) | (g[1] >>> 16)) + ((g[0] << 16) | (g[0] >>> 16));
x[3] = g[3] + ((g[2] << 8) | (g[2] >>> 24)) + g[1];
x[4] =
g[4] + ((g[3] << 16) | (g[3] >>> 16)) + ((g[2] << 16) | (g[2] >>> 16));
x[5] = g[5] + ((g[4] << 8) | (g[4] >>> 24)) + g[3];
x[6] =
g[6] + ((g[5] << 16) | (g[5] >>> 16)) + ((g[4] << 16) | (g[4] >>> 16));
x[7] = g[7] + ((g[6] << 8) | (g[6] >>> 24)) + g[5];
},
};
blrabbit.encrypt
= function (msg, pwd) {
return Rabbit.encrypt(msg, pwd);
};
blrabbit.decrypt
= function (msg_ed, pwd) {
return Rabbit.decrypt(msg_ed, pwd);
};
blrabbit.base64Encode = function (message) {
return Rabbit.base64Encode(message);
};
})(
typeof module !== "undefined" && module.exports
? module.exports
: (self.blrabbit = self.blrabbit || {})
);
`

@felipediel
Copy link
Collaborator

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants