Store passwords with unprecedented security.
January 4, 2021
"On the Internet, nobody knows you're a dog." Cloud services are pretty cloudy. Most famous giant companies did not protect our data as they claimed.
Those giants, who face public pressure, may not protect our data well; what about password managers storing all our passwords? ID Guard Offline extension claims that it uses end-to-end encryption and can prevent employees, not to mention hackers, from accessing our passwords. Is that true?
OK. Let's show you how to verify the security design!
ID Guard Offline might be the only password manager that tells users how to verify its security design.
No worry if you are not a geek! Just with a little patient, you can do this experiment!
Leaning Tower of Pisa by Saffron Blaze
First, our experiment purposes:
Extension architecture:
How does the app send passwords to the browser extension when we select the account to fill on the phone?
With ECDH algorithm, the app and extension generate a shared secret to encrypt the transportation of passwords.
There are a few steps to generate the shared secret:
Requirements: install and use ID Guard Offline app and extension.
Toggle a breakpoint to capture data in transit. Demonstrate with Edge here.
Click the extension menu to show extensions:
Click the background page
of ID Guard Offline extension to open the debug window:
Toggle breakpoint:
We need 4 clicks:
Sources
Page
background.js
onServerMessage
function and click on the line number on the left.Open a login page in the browser, http://www.stealmylogin.com/demo.html, for example. A QR code will appear:
Scan the QR code with ID Guard Offline app on your phone. The app can get the website and extension's public key from the QR code.
Do not use your real password in the experiment.
The app will launch a mobile browser to fill after selecting the account. Tap the address bar of the browser and copy the URL. Save the URL for analysis later. It looks like this:
https://app-link.bluespace.tech:8081/remote-fill/index.html#a=&t=1609300964&host=www.stealmylogin.com&to=15579832-e41c-4b17-8615-b6507a02dd4b&key=MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAELzVA%2B9qJXZJShDcwWxo5%2FWWQTOGi%2FuaRAi1%2BHrcLWw6vISQmzusRptXE%2BCTSVi2HWxQ3BQjCDDd%2FPqTyATgkeUyv3GbfBBXVw2q8LjVpt1wnlrFG729QsnExYVqgI5WP&iv=v6DyQ%2Bmx16mt71Ab&cipher=1Ug43zUPuRkQn74m1309FL0J5BNGcqT5FHcwubzYnpBLAscF%2Bn78RfmurjiWIgOP3cbZ1%2F5Kz%2Fa9sjWyZozdUv1HXmo3u0k3%2F16KkPGuWaaTsHt8uCV7tQP0MNIs84fxr4REnBY%3D
The text string before #
is a web page address. Those after #
are parameters or data for transportation. Each parameter is separated by &
in name
=value
format.
t=1609300964
is the filling time for expiration detection.host=www.stealmylogin.com
is the host name of the website.to=15579832-e41c-4b17-8615-b6507a02dd4b
is the address of extension, randomly generated for every QR code.key
is the app's public key for deriving shared secret with the extension's private key.iv
is the Initial Vector parameter for AES-256-GCM.cipher
is the encryption result of user name and passwords, etc.The debugging window will capture the transported message soon. It looks like this:
Inspect the message by moving your mouse to message
. The message
looks like this:
{
to: "15579832-e41c-4b17-8615-b6507a02dd4b",
from: "a3ae6e09-8b2c-43bf-a61b-08f4022adfc5",
ts: "1609300964",
id: "83072ef7-11fe-49fe-bac3-787f92881bbf",
data: "{
"key":"MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAELzVA+9qJXZJShDcwWxo5/WWQTOGi/uaRAi1+HrcLWw6vISQmzusRptXE+CTSVi2HWxQ3BQjCDDd/PqTyATgkeUyv3GbfBBXVw2q8LjVpt1wnlrFG729QsnExYVqgI5WP",
"iv":"v6DyQ+mx16mt71Ab",
"cipher":"1Ug43zUPuRkQn74m1309FL0J5BNGcqT5FHcwubzYnpBLAscF+n78RfmurjiWIgOP3cbZ1/5Kz/a9sjWyZozdUv1HXmo3u0k3/16KkPGuWaaTsHt8uCV7tQP0MNIs84fxr4REnBY="
}"
}
Save it for analysis later. The order does not matter.
Then we can conduct our analysis after gathering all those data.
Compare data sent from phone and received by the extension:
Data item | Sent | Received | Same? |
---|---|---|---|
Time | t=1609300964 | ts: "1609300964" | Y |
Extension address | to=15579832-...-b6507a02dd4b | to: "15579832-...-b6507a02dd4b" | Y |
ECC public key | key=MHY...5WP | "key":"MHY...5WP" | Y1 |
AES IV | iv=v6DyQ%2Bmx16mt71Ab | "iv":"v6DyQ+mx16mt71Ab" | Y1 |
Cipher | cipher=1Ug...BY%3D | "cipher":"1Ug...BY=" | Y1 |
Host | host=www.stealmylogin.com | NA | N |
Message ID | NA | id: "83072ef7-...-787f92881bbf" | N |
Sending address | NA | from: "a3ae6e09-...-08f4022adfc5" | N |
The hostname host=www.stealmylogin.com
is not sent to the extension. It only displays in the mobile browser. The cloud side has no idea which website is filling. No worry for privacy.
Sending address and message ID are generated by the web program in the mobile browser.
Dive into the source code
script.js
inhttps://app-link.bluespace.tech:8081/remote-fill/index.html
to confirm these. Will explain it later in theProgrammers' section
.
All data are here. It is easy to conclude whether passwords are sent to the cloud by comparing the transported data with the filling password. But we cannot confirm that: is it possible to send the encryption key to the cloud and let the cloud decipher the encrypted data?
We will then show you how to perform an in-depth inspection to verify whether the app sends the encryption key to the cloud.
The encryption parameters look weird and long(other data are quite simple). Is it possible they contain the encryption key?
Does key
piggyback encryption key?
Method: Is it 160 characters long?
Knowledge:
The length of the public key of ECC P-384 is 120 bytes in spki
format.
Base64 encoding transforms every 3 bytes into 4 characters.
Data
The captured key
(MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAELzVA+9qJXZJShDcwWxo5/WWQTOGi/uaRAi1+HrcLWw6vISQmzusRptXE+CTSVi2HWxQ3BQjCDDd/PqTyATgkeUyv3GbfBBXVw2q8LjVpt1wnlrFG729QsnExYVqgI5WP
) is 160 characters. No piggybacked data.
Does iv
piggyback encryption key?
Method: Is it 16 characters?
Knowledge:
IV
of AES-256-GCM
is a 12 random binary data.
Base64 encoding transforms every 3 bytes into 4 characters.
Data
The captured iv
(v6DyQ+mx16mt71Ab
) is 16 characters. No piggybacked data.
We can check whether the iv
is different each time, even for the same account or password.
Programmers can print the derived encryption key to see if they are the same.
Does cipher
piggyback encryption key?
Method: Can the extension fill password?
Knowledge:
The encryption algorithm AES-256-GCM
is an authenticated encryption that assures data's confidentiality and authenticity. Passwords cannot be decrypted whenever the ciphertext changes.
By doing these 3 checks, we can verify whether it is possible to send the encryption key to the cloud.
We just explained how to verify the security of transportation without source code. But programmers love source code. Let's dive in.
The source code of both extension and the web program is not minimized nor obfuscated. Easy to read, debug, and audit.
Look into the source code of https://app-link.bluespace.tech:8081/remote-fill/index.html
, we can find the main source code, script.js
.
Parse parameters from the mobile app.
const params = new URLSearchParams(window.location.hash);
const timestamp = params.get('t');
const host = params.get('host');
const to = params.get('to');
const key = params.get('key');
const iv = params.get('iv');
const cipher = params.get('cipher');
Make a JSON message from the parsed info 't,
to,
key,
iv,
cipher`.
const data = JSON.stringify({key: key, iv: iv, cipher: cipher});
const uuid = uuidv4();
const request = {to: to, from: uuid, ts: timestamp, id: uuidv4(), data: data};
host
is not in the message. The cloud side has no idea what websites we are filling into. You can have peace of mind.
Then send the message to the cloud via AJAX.
The message is received by websocket.onmessage
event. Then the message is passed to the onServerMessage
function. The decryption is in the decryptMessage
function in crypto.js
.
importPublicKeyText = (Base64Text) => window.crypto.subtle.importKey(this.publicKeyFormat, Base64.decode(Base64Text), this.curve, true, []);
deriveKey = (publicKey, privateKey) => window.crypto.subtle.deriveKey({name: "ECDH", public: publicKey}, privateKey, {name: "AES-GCM", length: 256}, true, ["encrypt", "decrypt"]);
decrypt = (ivBytes, cipherBytes, secretKey) => window.crypto.subtle.decrypt({name: "AES-GCM", iv: ivBytes}, secretKey, cipherBytes);
decryptMessage = async function(keyPair, data) {
const encrypted = JSON.parse(data);
const publicKey = await this.importPublicKeyText(encrypted.key);
const secretKey = await this.deriveKey(publicKey, keyPair.privateKey);
const ivBytes = Uint8Array.from(window.atob(encrypted.iv), c => c.charCodeAt(0));
const cipherBytes = Uint8Array.from(window.atob(encrypted.cipher), c => c.charCodeAt(0));
const bytes = await this.decrypt(ivBytes, cipherBytes, secretKey);
return new TextDecoder().decode(bytes);
};
Key steps:
importPublicKeyText
imports app's public key in spki
format;deriveKey
derives 256 bits AES shared secret/encryption key with ECDH
algorithm;decrypt
decrypts plaintext from the ciphertext with AES-GCM
mode. The GCM
mode of AES is an authenticated encryption that assures data's confidentiality and authenticity. Any change in the ciphertext can be detected and cause decryption failure.Although cryptography and network security are both very professional technical fields, we still hope that as many people can understand and verify the security technologies we use. We strive to create the most advanced security technology and try our best to provide verification methods when designing ID Guard Offline.
Some users may still have questions in mind if having no relevant knowledge. However, professionals in the area can figure out every detail by reading this explanation of the verification method.
More articles about ID Guard Offline extension...
Stop using browser extension password managers. Use password manager extension instead.
Our ID Guard Offline designers are always taking security very seriously. We do not adopt common accepted but not good enough designs blindly.
Security design of ID Guard Offline extension
We all know that encrypted ≠ secured. Military encryption is more of a advertising slogan to fool laymen layperson. It is the security design that keeps passwords safe.
End-to-end encryption is more secure than HTTPS
How secure? Better than HTTPS adopted by Internet banking.
How to verify extension design?
Two password managers | Others | ID Guard Offline |
---|---|---|
Trustee | The developer | No one |
How do I know if you do what you say? | Trust the developer. | There are guide articles telling you how to verify them by yourself. |