Skip to content
This repository has been archived by the owner on May 16, 2018. It is now read-only.

Commit

Permalink
4.10
Browse files Browse the repository at this point in the history
Add HOTP support
  • Loading branch information
Sneezry committed Apr 23, 2015
1 parent 8628167 commit c339901
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 37 deletions.
18 changes: 11 additions & 7 deletions _locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"description": "Scan QR Code."
},
"add_secret": {
"message": "Input Secret",
"description": "Input Secret."
"message": "Manual Entry",
"description": "Manual Entry."
},
"close": {
"message": "Close",
Expand All @@ -55,10 +55,6 @@
"message": "Secret",
"description": "Secret."
},
"exportWarning": {
"message": "Warning! You may lose your data if you do not know what you are doing!",
"description": "Export Warning."
},
"updateSuccess": {
"message": "Success.",
"description": "Update Success."
Expand Down Expand Up @@ -156,7 +152,15 @@
"description": "Capture Failed"
},
"unencrypted_secret_warning": {
"message": "This secret is not encrypted! Click here to open security setting to fix this issue.",
"message": "This secret is not encrypted! Click here to set a passphrase to fix this issue.",
"description": "Unencrypted Secret Warning"
},
"based_on_time": {
"message": "Time Based",
"description": "Time Based"
},
"based_on_counter": {
"message": "Counter Based",
"description": "Counter Based"
}
}
18 changes: 11 additions & 7 deletions _locales/zh_CN/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"description": "Scan QR Code."
},
"add_secret": {
"message": "输入密钥",
"description": "Input Secret."
"message": "手动输入",
"description": "Manual Entry."
},
"close": {
"message": "关闭",
Expand All @@ -55,10 +55,6 @@
"message": "密钥",
"description": "Secret."
},
"exportWarning": {
"message": "警告!如果你不知道正在做什么可能会丢失你的数据!",
"description": "Export Warning."
},
"updateSuccess": {
"message": "成功。",
"description": "Update Success."
Expand Down Expand Up @@ -156,7 +152,15 @@
"description": "Capture Failed"
},
"unencrypted_secret_warning": {
"message": "此密钥未被加密!点击此处打开安全设置以解决此问题",
"message": "此密钥未被加密!点击此处来设置一个密码以解决此问题",
"description": "Unencrypted Secret Warning"
},
"based_on_time": {
"message": "基于时间",
"description": "Time Based"
},
"based_on_counter": {
"message": "基于计数器",
"description": "Counter Based"
}
}
44 changes: 37 additions & 7 deletions css/popup.css
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ body {
font-size: 12px;
padding: 0 10px;
margin: 0 4px;
width: 290px;
width: 250px;
bottom: 4px;
left: 0;
background: #EC6959;
Expand Down Expand Up @@ -227,7 +227,7 @@ body {
}

#codes.edit .code {
color: gray;
color: #CCC!important;
-webkit-user-select: none;
cursor: default;
}
Expand Down Expand Up @@ -258,10 +258,20 @@ body {
display: block;
}

#codes.timeout .code {
#codes.timeout .code:not(.hotp) {
-webkit-animation: twinkling 1s infinite ease-in-out;
}

.hotp {
color: #555;
cursor: default;
}

.hotp[hasCode="true"] {
color: #08C;
cursor: pointer;
}

.movehandle {
height: 98px;
line-height: 98px;
Expand Down Expand Up @@ -390,15 +400,33 @@ body {
cursor: pointer;
}

.sector {
.counter {
color: #888;
font-size: 18px;
text-align: center;
cursor: pointer;
}

.counter:not([disabled="true"]):hover {
color: #000;
}

.counter[disabled="true"] {
color: #CCC;
cursor: default;
}

.sector,
.counter {
width: 20px;
height: 20px;
position: absolute;
right: 10px;
bottom: 10px;
}

#codes.edit .sector {
#codes.edit .sector,
#codes.edit .counter {
display: none;
}

Expand Down Expand Up @@ -616,12 +644,14 @@ body {
outline: none;
}

.checkbox_group input[type="checkbox"] {
.checkbox_group input[type="checkbox"],
.radio_group input[type="radio"] {
display: inline-block !important;
width: auto !important;
}

.checkbox_group label {
.checkbox_group label,
.radio_group label {
display: inline-block !important;
margin-left: 0 !important;
}
Expand Down
15 changes: 13 additions & 2 deletions javascript/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function getQr(tab, left, top, width, height, windowWidth){

function getTotp(text){
var id = this.tab.id;
if(text.indexOf('otpauth://totp/') != 0){
if(text.indexOf('otpauth://') != 0){
if(text == 'error decoding QR Code'){
chrome.tabs.sendMessage(id, {action: 'errorqr'});
}
Expand All @@ -58,7 +58,9 @@ function getTotp(text){
}
}
else{
var uri = text.split('otpauth://totp/')[1];
var uri = text.split('otpauth://')[1];
var type = uri.substr(0,4).toLowerCase();
uri = uri.substr(5);
var label = uri.split('?')[0];
var parameters = uri.split('?')[1];
if(!label || !parameters){
Expand All @@ -83,6 +85,10 @@ function getTotp(text){
else if(parameter[0].toLowerCase() == 'issuer'){
issuer = parameter[1];
}
else if(parameter[0].toLowerCase() == 'counter'){
counter = Number(parameter[1]);
counter = (isNaN(counter)||counter<0)?0:counter;
}
}
if(!secret){
chrome.tabs.sendMessage(id, {action: 'errorqr'});
Expand All @@ -98,6 +104,7 @@ function getTotp(text){
addSecret[CryptoJS.MD5(secret)] = {
account: account||'',
issuer: issuer||'',
type: type,
secret: CryptoJS.AES.encrypt(secret, decodedPhrase).toString(),
index: index,
encrypted: true
Expand All @@ -107,10 +114,14 @@ function getTotp(text){
addSecret[CryptoJS.MD5(secret)] = {
account: account||'',
issuer: issuer||'',
type: type,
secret: secret,
index: index
}
}
if('hotp' === type && counter !== undefined){
addSecret[CryptoJS.MD5(secret)].counter = counter;
}
chrome.storage.sync.set(addSecret, function(){
chrome.tabs.sendMessage(id, {action: 'added', account: account});
});
Expand Down
51 changes: 43 additions & 8 deletions javascript/popup.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var totp = new KeyUtilities();
var getCode = totp.generate;
var otp = new KeyUtilities();
var getCode = otp.generate;
var _secret = [];
var deleteIdList = [];
var deleteKeyList = [];
Expand Down Expand Up @@ -32,12 +32,13 @@ else if(document.cookie){
document.getElementById('extName').innerText = chrome.i18n.getMessage('extShortName');
document.getElementById('add_qr').innerText = chrome.i18n.getMessage('add_qr');
document.getElementById('add_secret').innerText = chrome.i18n.getMessage('add_secret');
document.getElementById('totp_label').innerText = chrome.i18n.getMessage('based_on_time');
document.getElementById('hotp_label').innerText = chrome.i18n.getMessage('based_on_counter');
document.getElementById('add_button').innerText = chrome.i18n.getMessage('ok');
document.getElementById('message_close').innerText = chrome.i18n.getMessage('ok');
document.getElementById('account_label').innerText = chrome.i18n.getMessage('account');
document.getElementById('secret_label').innerText = chrome.i18n.getMessage('secret');
document.getElementById('menuName').innerText = chrome.i18n.getMessage('settings');

document.getElementById('security_new_phrase_label').innerText = chrome.i18n.getMessage('phrase');
document.getElementById('security_confirm_phrase_label').innerText = chrome.i18n.getMessage('confirm_phrase');
document.getElementById('security_warning').innerText = chrome.i18n.getMessage('security_warning');
Expand Down Expand Up @@ -325,6 +326,7 @@ function updateSecret(callback){
function saveSecret(){
var account = document.getElementById('account_input').value;
var secret = document.getElementById('secret_input').value;
var type = document.getElementById('totp').checked?'totp':'hotp';
if(!account || !secret){
showMessage(chrome.i18n.getMessage('err_acc_sec'));
return;
Expand All @@ -337,6 +339,7 @@ function saveSecret(){
addSecret[CryptoJS.MD5(secret)] = {
account: account,
issuer: '',
type: type,
secret: CryptoJS.AES.encrypt(secret, decodedPhrase).toString(),
index: index,
encrypted: true
Expand All @@ -346,10 +349,14 @@ function saveSecret(){
addSecret[CryptoJS.MD5(secret)] = {
account: account,
issuer: '',
type: type,
secret: secret,
index: index
}
}
if('hotp' === type){
addSecret[CryptoJS.MD5(secret)].counter = 0;
}
chrome.storage.sync.set(addSecret);
document.getElementById('infoAction').className = '';
document.getElementById('addAccount').className = '';
Expand Down Expand Up @@ -498,7 +505,7 @@ function updateCode(){
}, 200);
}
}
else{
else if(_secret[i].type !== 'hotp'){
document.getElementById('code-'+i).innerText = getCode(_secret[i].secret);
}
}
Expand Down Expand Up @@ -589,10 +596,10 @@ function showCodes(result){
el.id = 'codeBox-'+i;
el.className = 'codeBox';
el.innerHTML = '<div class="deleteAction" codeId="'+i+'" key="'+_secret[i].hash+'"><i class="fa fa-minus-circle"></i></div>'+
'<div class="sector"></div>'+
('hotp'===_secret[i].type?'<div codeId="'+i+'" class="counter"><i class="fa fa-refresh"></i></div>':'<div class="sector"></div>')+
(_secret[i].issuer?('<div class="issuer">'+_secret[i].issuer+'</div>'):'')+
'<div class="issuerEdit"><input class="issuerEditBox" type="text" codeId="'+i+'" value="'+(_secret[i].issuer?_secret[i].issuer:'')+'" /></div>'+
'<div class="code" id="code-'+i+'">&bull;&bull;&bull;&bull;&bull;&bull;</div>'+
'<div class="code'+('hotp'===_secret[i].type?' hotp':'')+'" id="code-'+i+'">&bull;&bull;&bull;&bull;&bull;&bull;</div>'+
'<div class="account">'+_secret[i].account+'</div>'+
'<div class="accountEdit"><input class="accountEditBox" type="text" codeId="'+i+'" value="'+_secret[i].account+'" /></div>'+
'<div id="showqr-'+i+'" class="showqr"><i class="fa fa-qrcode"></i></div>'+
Expand Down Expand Up @@ -625,6 +632,10 @@ function showCodes(result){
for(var i=0; i<showQrAction.length; i++){
showQrAction[i].onclick = showQr;
}
var counterAction = document.getElementsByClassName('counter');
for(var i=0; i<counterAction.length; i++){
counterAction[i].onclick = getNewHotpCode;
}
var accountEditBox = document.getElementsByClassName('accountEditBox');
for(var i=0; i<accountEditBox.length; i++){
accountEditBox[i].onblur = saveAccount;
Expand Down Expand Up @@ -697,7 +708,7 @@ function showQr(){
codeId = Number(codeId);
var secret = _secret[codeId];
var label = secret.issuer?(secret.issuer+':'+secret.account):secret.account;
var otpauth = 'otpauth://totp/'+label+'?secret='+secret.secret+(secret.issuer?('&issuer='+secret.issuer):'');
var otpauth = 'otpauth://'+(secret.type||'totp')+'/'+label+'?secret='+secret.secret+(secret.issuer?('&issuer='+secret.issuer):'')+(('hotp'===secret.type&&secret.counter)?('&counter='+secret.counter):'');
var qrcode = new QRCode('qr', {
text: otpauth,
width: 128,
Expand All @@ -718,7 +729,6 @@ function showExport(){
document.getElementById('export').className = 'fadein';
setTimeout(function(){
document.getElementById('export').style.opacity = 1;
//showMessage(chrome.i18n.getMessage('exportWarning'));
chrome.storage.sync.get(function(data){
document.getElementById('exportData').value = JSON.stringify(data);
});
Expand Down Expand Up @@ -869,6 +879,31 @@ function syncTimeWithGoogle(showStatusBox){
xhr.send();
}

function getNewHotpCode(){
var codeId = this.getAttribute('codeId');
if(this.getAttribute('disabled')=='true'){
return;
}
if(document.getElementById('code-'+codeId).innerText=='Encrypted'){
document.getElementById('passphrase').className = 'fadein';
setTimeout(function(){
document.getElementById('passphrase').style.opacity = 1;
}, 200);
return;
}
this.setAttribute('disabled', 'true');
setTimeout(function(){
this.removeAttribute('disabled');
}.bind(this), 5000);
document.getElementById('code-'+codeId).setAttribute('hasCode', 'true');
document.getElementById('code-'+codeId).innerText = getCode(_secret[codeId].secret, _secret[codeId].counter);
_secret[codeId].counter++;
chrome.storage.sync.get(function(secret){
secret[CryptoJS.MD5(_secret[codeId].secret)].counter = _secret[codeId].counter;
chrome.storage.sync.set(secret);
});
}

(function(){
var clientTime = new Date();
clientTime = Math.floor(clientTime.getTime()/1000/3600/24);
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "__MSG_extName__",
"short_name": "__MSG_extShortName__",
"version": "4.9",
"version": "4.10",
"default_locale": "en",
"description": "__MSG_extDesc__",
"icons": {
Expand Down
8 changes: 8 additions & 0 deletions popup.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@
<input type="text" id="account_input" />
<label for="secret_input" id="secret_label"></label>
<input type="text" id="secret_input" />
<div class="radio_group">
<input type="radio" id="totp" name="otp_type" checked="true" />
<label for="totp" id="totp_label"></label>
</div>
<div class="radio_group">
<input type="radio" id="hotp" name="otp_type" />
<label for="hotp" id="hotp_label"></label>
</div>
<div id="add_button"></div>
</div>
</div>
Expand Down
Loading

0 comments on commit c339901

Please sign in to comment.