Skip to content
This repository was archived by the owner on Jan 19, 2021. It is now read-only.

Commit f389ffb

Browse files
committed
Initial (very, very raw) dev release
0 parents  commit f389ffb

File tree

16 files changed

+1809
-0
lines changed

16 files changed

+1809
-0
lines changed

.editorconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 4
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true
10+
max_line_length = 100
11+
12+
[Makefile]
13+
indent_style = tab

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/chromium
2+
/firefox
3+
/dist
4+
/dist-webstore
5+
6+
/src/node_modules
7+
/src/css
8+
/src/js
9+
/src/*.log
10+
11+
*.pem
12+
*.crx

.version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.1.0-dev

LICENSE

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
ISC License
2+
3+
Copyright (c) 2019, Maxim Baz & Steve Gilberd
4+
5+
Permission to use, copy, modify, and/or distribute this software for any
6+
purpose with or without fee is hereby granted, provided that the above
7+
copyright notice and this permission notice appear in all copies.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Makefile

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
VERSION ?= $(shell cat .version)
2+
3+
CLEAN_FILES := chromium firefox dist dist-webstore
4+
CHROME := $(shell which chromium 2>/dev/null || which chromium-browser 2>/dev/null || which chrome 2>/dev/null || which google-chrome 2>/dev/null || which google-chrome-stable 2>/dev/null)
5+
6+
#######################
7+
# For local development
8+
9+
.PHONY: all
10+
all: extension chromium firefox
11+
12+
.PHONY: extension
13+
extension:
14+
$(MAKE) -C src
15+
16+
EXTENSION_FILES := \
17+
src/*.css \
18+
src/*.png \
19+
src/*.svg \
20+
src/fonts/* \
21+
src/popup/*.html \
22+
src/popup/*.svg
23+
EXTENSION_FILES := \
24+
$(wildcard $(EXTENSION_FILES)) \
25+
src/css/popup.dist.css \
26+
src/js/background.dist.js \
27+
src/js/popup.dist.js \
28+
src/js/inject.dist.js
29+
CHROMIUM_FILES := $(patsubst src/%,chromium/%, $(EXTENSION_FILES))
30+
FIREFOX_FILES := $(patsubst src/%,firefox/%, $(EXTENSION_FILES))
31+
32+
.PHONY: chromium
33+
chromium: extension $(CHROMIUM_FILES) chromium/manifest.json
34+
35+
$(CHROMIUM_FILES) : chromium/% : src/%
36+
[ -d $(dir $@) ] || mkdir -p $(dir $@)
37+
cp $< $@
38+
39+
chromium/manifest.json : src/manifest-chromium.json
40+
[ -d $(dir $@) ] || mkdir -p $(dir $@)
41+
cp $< $@
42+
43+
.PHONY: firefox
44+
firefox: extension $(FIREFOX_FILES) firefox/manifest.json
45+
46+
$(FIREFOX_FILES) : firefox/% : src/%
47+
[ -d $(dir $@) ] || mkdir -p $(dir $@)
48+
cp $< $@
49+
50+
firefox/manifest.json : src/manifest-firefox.json
51+
[ -d $(dir $@) ] || mkdir -p $(dir $@)
52+
cp $< $@
53+
54+
#######################
55+
# For official releases
56+
57+
.PHONY: clean
58+
clean:
59+
rm -rf $(CLEAN_FILES)
60+
$(MAKE) -C src clean
61+
62+
.PHONY: crx-webstore
63+
crx-webstore:
64+
"$(CHROME)" --disable-gpu --pack-extension=./chromium --pack-extension-key=webstore.pem
65+
mv chromium.crx browserpass-otp-webstore.crx
66+
67+
.PHONY: crx-github
68+
crx-github:
69+
"$(CHROME)" --disable-gpu --pack-extension=./chromium --pack-extension-key=github.pem
70+
mv chromium.crx browserpass-otp-github.crx
71+
72+
.PHONY: dist
73+
dist: clean extension chromium firefox crx-webstore crx-github
74+
mkdir -p dist
75+
76+
git archive -o dist/browserpass-otp-$(VERSION).tar.gz --format tar.gz --prefix=browserpass-otp-$(VERSION)/ $(VERSION)
77+
78+
(cd chromium && zip -r ../dist/browserpass-otp-chromium-$(VERSION).zip *)
79+
(cd firefox && zip -r ../dist/browserpass-otp-firefox-$(VERSION).zip *)
80+
81+
mv browserpass-otp-webstore.crx dist/browserpass-otp-webstore-$(VERSION).crx
82+
mv browserpass-otp-github.crx dist/browserpass-otp-github-$(VERSION).crx
83+
84+
for file in dist/*; do \
85+
gpg --detach-sign --armor "$$file"; \
86+
done
87+
88+
mkdir -p dist-webstore
89+
90+
cp dist/browserpass-otp-firefox-$(VERSION).zip dist-webstore/firefox-$(VERSION).zip
91+
mv dist/browserpass-otp-$(VERSION).tar.gz dist-webstore/firefox-$(VERSION)-src.tar.gz
92+
93+
cp -a chromium dist-webstore/
94+
sed -i '/"key"/d' dist-webstore/chromium/manifest.json
95+
(cd dist-webstore/chromium && zip -r ../chrome-$(VERSION).zip *)
96+
rm -rf dist-webstore/chromium

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"dependencies": {
3+
"base32-decode": "^1.0.0"
4+
}
5+
}

src/Makefile

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
BROWSERIFY := node_modules/.bin/browserify
2+
PRETTIER := node_modules/.bin/prettier
3+
LESSC := node_modules/.bin/lessc
4+
5+
CLEAN_FILES := js
6+
PRETTIER_FILES := $(wildcard *.json *.js popup/*.js *.less popup/*.less *.html popup/*.html)
7+
8+
.PHONY: all
9+
all: deps prettier css/popup.dist.css js/background.dist.js js/popup.dist.js js/inject.dist.js
10+
11+
.PHONY: deps
12+
deps:
13+
yarn install
14+
15+
.PHONY: prettier
16+
prettier: $(PRETTIER) $(PRETTIER_FILES)
17+
$(PRETTIER) --write $(PRETTIER_FILES)
18+
19+
css/popup.dist.css: $(LESSC) popup/popup.less
20+
[ -d css ] || mkdir -p css
21+
$(LESSC) popup/popup.less css/popup.dist.css
22+
23+
js/background.dist.js: $(BROWSERIFY) background.js
24+
[ -d js ] || mkdir -p js
25+
$(BROWSERIFY) -o js/background.dist.js background.js
26+
27+
js/popup.dist.js: $(BROWSERIFY) popup/*.js
28+
[ -d js ] || mkdir -p js
29+
$(BROWSERIFY) -o js/popup.dist.js popup/popup.js
30+
31+
js/inject.dist.js: $(BROWSERIFY) inject.js
32+
[ -d js ] || mkdir -p js
33+
$(BROWSERIFY) -o js/inject.dist.js inject.js
34+
35+
# Firefox requires the last command to evaluate to something serializable
36+
# https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript#Return_value
37+
echo ";undefined" >> js/inject.dist.js
38+
39+
.PHONY: clean
40+
clean:
41+
rm -rf $(CLEAN_FILES)

src/background.js

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
"use strict";
2+
3+
require("chrome-extension-async");
4+
const hash = require("hash.js");
5+
const Authenticator = require("otplib").authenticator.Authenticator;
6+
7+
const validSenders = [
8+
"naepdomgkenhinolocfifgehidddafch",
9+
"pjmbgaakjkbhpopmakjoedenlfdmcdgm",
10+
"klfoddkbhleoaabpmiigbmpbjfljimgb",
11+
12+
];
13+
14+
// Main entry point, invoked from browserpass. No response is expected.
15+
chrome.runtime.onMessageExternal.addListener(function(request, sender) {
16+
// reject invalid senders
17+
if (!validSenders.includes(sender.id)) {
18+
return;
19+
}
20+
21+
// parse OTP object
22+
if (request.otp.key === null) {
23+
// this is an OTP URI, so extract the pieces
24+
try {
25+
let url = new URL(request.otp.data.toLowerCase());
26+
let parts = url.pathname.split("/").filter(s => s.trim());
27+
var otp = {
28+
type: parts[0],
29+
secret: url.searchParams.get("secret").toUpperCase(),
30+
algorithm: url.searchParams.get("algorithm") || "sha1",
31+
digits: parseInt(url.searchParams.get("digits") || "6"),
32+
period: parseInt(url.searchParams.get("period") || "30")
33+
};
34+
} catch (e) {
35+
console.log(`Unable to parse uri: ${request.otp.data}`, e);
36+
return;
37+
}
38+
} else {
39+
var otp = {
40+
type: request.otp.key.toLowerCase(),
41+
secret: request.otp.data.toUpperCase(),
42+
algorithm: "sha1",
43+
digits: 6,
44+
period: 30
45+
};
46+
}
47+
48+
// fix default type
49+
if (otp.type === "otp") {
50+
otp.type = "totp";
51+
}
52+
53+
// set handler
54+
if (otp.type === "totp") {
55+
otp.generate = makeTOTP.bind(otp);
56+
} else {
57+
console.log(`Unsupported OTP type: ${otp.type}`);
58+
}
59+
60+
// generate code
61+
copyToClipboard(otp.generate());
62+
});
63+
64+
/**
65+
* Gemerate a TOTP code
66+
*
67+
* @return string Generated code
68+
*/
69+
function makeTOTP() {
70+
switch (this.algorithm) {
71+
case "sha1":
72+
case "sha256":
73+
case "sha512":
74+
break;
75+
default:
76+
throw new Error(`Unsupported TOTP algorithm: ${this.algorithm}`);
77+
}
78+
79+
var generator = new Authenticator();
80+
generator.options = {
81+
crypto: {
82+
createHmac: (a, k) => hash.hmac(hash[a], k)
83+
},
84+
algorithm: this.algorithm,
85+
digits: this.digits,
86+
step: this.period
87+
};
88+
89+
return generator.generate(this.secret);
90+
}
91+
92+
/**
93+
* Copy text to clipboard
94+
*
95+
* @since 3.0.0
96+
*
97+
* @param string text Text to copy
98+
* @return void
99+
*/
100+
function copyToClipboard(text) {
101+
document.addEventListener(
102+
"copy",
103+
function(e) {
104+
e.clipboardData.setData("text/plain", text);
105+
e.preventDefault();
106+
},
107+
{ once: true }
108+
);
109+
document.execCommand("copy");
110+
}

src/inject.js

Whitespace-only changes.

src/manifest-chromium.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzCCoXUbvVtAC6rN7QNTLIQ/ThQWBcp9TgeS0HOcpkUxOypD0fyJDMv2U3c6yuCwIqmBa+LwDncLbSyhb788N6hc4+01QWKzQa9qjpAWKHTx1erKxs8+OjbdTxJBgfKI9s9hVUuBTeNBv4PoC1pv3F2wk0HyZct63GcMCikZMMri/3/HRXTPAsT+ROxwrohsyZLSg4FptrNYPQb/7XpPS1+eHOqzNqv0Zhh6/gJSJ5gML6tKjudjnhF0pi6weKbvkIlf9g2nT/Wo8iarimJX49ENqpSuqP+BFpspoptwyIqfUmi3NQZXDOXkyg9DYQvXjU4+yrVmJs7XpzU9RdNDe9wIDAQAB",
3+
"manifest_version": 2,
4+
"name": "Browserpass OTP",
5+
"description": "OTP extension for browserpass",
6+
"version": "3.0.0",
7+
"author": "Maxim Baz <[email protected]>, Steve Gilberd <[email protected]>",
8+
"homepage_url": "https://github.com/browserpass/browserpass-otp",
9+
"background": {
10+
"persistent": true,
11+
"scripts": ["js/background.dist.js"]
12+
},
13+
"permissions": ["clipboardWrite"]
14+
}

0 commit comments

Comments
 (0)