forked from openpgpjs/openpgpjs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adding restructured GPG4Browsers code
- created a test suite available at test/index.html - fixed a bug in MD5 calculation
- Loading branch information
Carsten Wentzlow
committed
Dec 9, 2011
1 parent
0526a24
commit 81212f2
Showing
57 changed files
with
13,985 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | ||
<html> | ||
<head> | ||
<script type="text/javascript"> | ||
//GPG4Browsers - An OpenPGP implementation in javascript | ||
//Copyright (C) 2011 Recurity Labs GmbH | ||
// | ||
//This library is free software; you can redistribute it and/or | ||
//modify it under the terms of the GNU Lesser General Public | ||
//License as published by the Free Software Foundation; either | ||
//version 2.1 of the License, or (at your option) any later version. | ||
// | ||
//This library is distributed in the hope that it will be useful, | ||
//but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
//Lesser General Public License for more details. | ||
// | ||
//You should have received a copy of the GNU Lesser General Public | ||
//License along with this library; if not, write to the Free Software | ||
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
|
||
var tab_registry = new Array(); | ||
|
||
var account_name = null; | ||
|
||
/** | ||
* Event listener for chrom.extension message interface. | ||
* This is the main data exchange interface for communication between windows. | ||
*/ | ||
function onRequest(request, sender, sendResponse) { | ||
// only the extension itself | ||
if (document.URL.split("/")[2] != sender.id) | ||
return; | ||
|
||
/* the following code is currently not working, but a check for incognito mode would be nice to have here. | ||
if (chrome.extension.inIncognitoContext != true) | ||
alert("enable incognito mode for GPG4Browsers Extension!"+JSON.stringify(chrome.extension.inIncognitoContext)); | ||
*/ | ||
|
||
|
||
// Show the page action for the tab that the sender (content script) | ||
// was on. | ||
if (tab_registry[sender.tab.id] != null) { | ||
|
||
sendResponse(tab_registry[sender.tab.id]); | ||
tab_registry[sender.tab.id] = null; | ||
return; | ||
} | ||
// page action... open the pgp tab with compose | ||
if (request.action == 0) { | ||
openComposeWindow(request); | ||
sendResponse({}); | ||
return; | ||
} | ||
// request from contentscript on gmail interface to open a openpgp window with a message to decrypt/verify | ||
if (request.action == 1) { | ||
openComposeWindow(request); | ||
sendResponse({}); | ||
return; | ||
} | ||
|
||
// openpgp is requesting to open a gmail compose window | ||
if (request.action == 2 && sender.tab.id) { | ||
openGmailComposeWindow(request); | ||
sendResponse({}); | ||
return; | ||
} | ||
// contentscript on gmail compose window requesting the message | ||
// not used due to missing implemenation | ||
if (request.action == 3 && sender.tab.id) { | ||
sendResponse(tab_registry[sender.tab.id]); | ||
return; | ||
} | ||
|
||
account_name = request.account; | ||
chrome.pageAction.show(sender.tab.id); | ||
|
||
// Return nothing to let the connection be cleaned up. | ||
sendResponse({}); | ||
} | ||
|
||
chrome.pageAction.onClicked.addListener(pageActionListener); | ||
|
||
/** | ||
* opens the Gmail ComposeWindow and transmits the email data | ||
* @param to string of recipient email addresses separated by ", " | ||
* @param cc string of recipient email addresses separated by ", " receiving a copy | ||
* @param cc string of recipient email addresses separated by ", " receiving a blind copy | ||
* @param subject email subject as string | ||
*/ | ||
function openGmailComposeWindow(request) { | ||
var tab = chrome.tabs.create( | ||
{url: "https://mail.google.com/mail/?view=cm&fs=1&tf=1&to="+ | ||
encodeURIComponent(request.to)+"&cc="+ | ||
encodeURIComponent(request.cc)+"&bcc="+ | ||
encodeURIComponent(request.bcc)+"&su="+ | ||
encodeURIComponent(request.subject)+"&body="+ | ||
// TODO: long bodys result in an error on the google mail server because the URL gets too long | ||
encodeURIComponent(request.body)+"&shva=1", selected: true}); | ||
// its a good idea to store the request... | ||
// once the gmail compose window has opened, the content | ||
// script could fetch the request to insert message data | ||
// into the forms this would be a proper solution to the | ||
// "url too long" issue. Problem: the page is rendered | ||
// within an iframe so contentscript has no access to | ||
// fill in the data. We have'nt tried the basic html | ||
// approach yet.. see action == "3" | ||
tab_registry[tab.id] = request; | ||
} | ||
|
||
/** | ||
* the page action listener event handler: | ||
* opens a compose window (openpgp.html) | ||
*/ | ||
function pageActionListener(tab) { | ||
openComposeWindow({action: 0, account: account_name}); | ||
} | ||
|
||
/** | ||
* | ||
*/ | ||
function openComposeWindow(request) { | ||
var tab = chrome.tabs.create({url: "openpgp.html", selected: true }, function(tab) { | ||
tab_registry[tab.id] = request; | ||
}); | ||
} | ||
|
||
// Listen for the content script to send a message to the background page. | ||
chrome.extension.onRequest.addListener(onRequest); | ||
</script> | ||
</head> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
// GPG4Browsers - An OpenPGP implementation in javascript | ||
// Copyright (C) 2011 Recurity Labs GmbH | ||
// | ||
// This library is free software; you can redistribute it and/or | ||
// modify it under the terms of the GNU Lesser General Public | ||
// License as published by the Free Software Foundation; either | ||
// version 2.1 of the License, or (at your option) any later version. | ||
// | ||
// This library is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
// Lesser General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU Lesser General Public | ||
// License along with this library; if not, write to the Free Software | ||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
|
||
|
||
if (window.location.href.indexOf("https://mail.google.com/mail/?view=cm") == 0) { | ||
// we are running in the compose window | ||
} else { | ||
// we are running in the normal interface | ||
chrome.extension.sendRequest({account: document.getElementsByTagName("script")[4].text.split(",")[10].replace(/"/g,"").trim()}, function(response) {}); | ||
|
||
} | ||
|
||
var current_message_type = -1; | ||
var current_message = null; | ||
|
||
/** | ||
* searches the given text for a pgp message. If a message is available the openpgp message dialog is shown | ||
* @param text text to be searched | ||
*/ | ||
function find_openpgp(text) { | ||
text = text.replace(/\r\n/g,"\n"); | ||
if (document.location.hash != current_message) { | ||
if (/-----BEGIN PGP MESSAGE-----/.test(text) && /-----END PGP MESSAGE-----/.test(text)) { | ||
current_message= document.location.hash; | ||
current_message_type = 0; | ||
current_pgp_block = text.substring(text.indexOf("-----BEGIN PGP MESSAGE-----"), text.indexOf("-----END PGP MESSAGE-----")+25); | ||
current_pgp_block = current_pgp_block.replace(/\n/g,"").replace(/<br>/g,"\n").replace(/<wbr>/g,""); | ||
if (pgp_verifyCheckSum(current_pgp_block)) | ||
show_pgp_alert(); | ||
|
||
} else if (/-----BEGIN PGP SIGNED MESSAGE-----/.test(text) && /-----END PGP SIGNATURE-----/.test(text)) { | ||
current_message= document.location.hash; | ||
current_message_type = 1; | ||
current_pgp_block = text.substring(text.indexOf("-----BEGIN PGP SIGNED MESSAGE-----"), text.indexOf("-----END PGP SIGNATURE-----")+26); | ||
current_pgp_block = current_pgp_block.replace(/\n/g,"").replace(/<br>/g,"\n").replace(/<wbr>/g,""); | ||
if (pgp_verifyCheckSum(current_pgp_block.substring(current_pgp_block.indexOf("-----BEGIN PGP SIGNATURE-----")))) | ||
show_pgp_alert(); | ||
} else { | ||
hide_pgp_alert(); | ||
} | ||
} | ||
} | ||
|
||
var doc = null; | ||
|
||
/** | ||
* call routine to open the openpgp.html page for handling a message | ||
* @return null | ||
*/ | ||
function start_pgp_dialog() { | ||
//Gmail does not provide a generic way. to get message data out of the HTML interface so we parse the DOM | ||
Gmail.getMail(function(msg) { | ||
msg.action = 1; | ||
chrome.extension.sendRequest(msg, function(response) { | ||
// hide_pgp_alert(); // hide pgp alert after opening the openpgp window | ||
}); | ||
}); | ||
} | ||
|
||
/** | ||
* showing the pgp alert | ||
* @return | ||
*/ | ||
function show_pgp_alert() { | ||
var div = document.createElement("div"); | ||
var buttonyes = document.createElement("button"); | ||
var buttonno = document.createElement("button"); | ||
buttonyes.setAttribute("type", "submit"); | ||
buttonyes.addEventListener("mousedown", function () { | ||
var msg = start_pgp_dialog(); | ||
}); | ||
buttonno.setAttribute("type", "submit"); | ||
buttonno.addEventListener("mousedown", function() { hide_pgp_alert(); }, true); | ||
buttonyes.appendChild(document.createTextNode("Yes")); | ||
buttonno.appendChild(document.createTextNode("No")); | ||
div.setAttribute("id", "gpg4browsers_alert"); | ||
div.setAttribute("style","position: fixed; top: 0px; width: 100%; background-color: #eeeeff; border-bottom: 1px solid #aaa;"); | ||
if (current_message_type == 0) | ||
div.appendChild(document.createTextNode("This mail is encrypted. Do you want to open it with GPG4Browsers?")); | ||
else if (current_message_type == 1) | ||
div.appendChild(document.createTextNode("This mail is signed. Do you want to open it with GPG4Browsers?")); | ||
div.appendChild(buttonyes); | ||
div.appendChild(buttonno); | ||
document.body.appendChild(div); | ||
}; | ||
|
||
/** | ||
* hiding the pgp alert | ||
* @return | ||
*/ | ||
function hide_pgp_alert() { | ||
if (document.getElementById("gpg4browsers_alert") != null) { | ||
document.getElementById("gpg4browsers_alert").parentNode.removeChild(document.getElementById("gpg4browsers_alert")); | ||
} | ||
} | ||
|
||
/** | ||
* background process timer to constantly check the displayed page for pgp messages | ||
*/ | ||
window.setInterval(function() { | ||
find_openpgp(document.body.innerHTML); | ||
if (document.getElementById("canvas_frame") != null) | ||
find_openpgp(document.getElementById("canvas_frame").contentDocument.body.innerHTML); | ||
}, 1000); | ||
|
||
|
||
/** | ||
* verifies the checksum of an base64 encrypted pgp block | ||
* @param text containing the base64 block and the base64 encoded checksum | ||
* @return true if the checksum was correct, false otherwise | ||
*/ | ||
function pgp_verifyCheckSum(text) { | ||
var splittedtext = text.split('-----'); | ||
var data = r2s(splittedtext[2].split('\n\n')[1].split("\n=")[0]); | ||
var checksum = splittedtext[2].split('\n\n')[1].split("\n=")[1].replace(/\n/g,""); | ||
var c = getCheckSum(data); | ||
var d = checksum; | ||
return c[0] == d[0] && c[1] == d[1] && c[2] == d[2]; | ||
} | ||
|
||
/** | ||
* calculates the checksum over a given block of data | ||
* @param data block to be used | ||
* @return a string containing the base64 encoded checksum | ||
*/ | ||
function getCheckSum(data) { | ||
var c = createcrc24(data); | ||
var str = "" + String.fromCharCode(c >> 16)+ | ||
String.fromCharCode((c >> 8) & 0xFF)+ | ||
String.fromCharCode(c & 0xFF); | ||
return s2r(str); | ||
} | ||
|
||
|
||
/** | ||
* calculation routine for a CRC-24 checksum | ||
* @param data | ||
* @return | ||
*/ | ||
function createcrc24 (data) { | ||
var crc = 0xB704CE; | ||
var i; | ||
var mypos = 0; | ||
var len = data.length; | ||
while (len--) { | ||
crc ^= (data[mypos++].charCodeAt()) << 16; | ||
for (i = 0; i < 8; i++) { | ||
crc <<= 1; | ||
if (crc & 0x1000000) | ||
crc ^= 0x1864CFB; | ||
} | ||
} | ||
return crc & 0xFFFFFF; | ||
} | ||
|
||
// base64 implementation | ||
|
||
var b64s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; | ||
|
||
/** | ||
* Converting Base64 data to a string | ||
* @param t base64 encoded data string | ||
* @return data string | ||
*/ | ||
function r2s(t) { | ||
var c, n; | ||
var r = '', s = 0, a = 0; | ||
var tl = t.length; | ||
|
||
for (n = 0; n < tl; n++) { | ||
c = b64s.indexOf(t.charAt(n)); | ||
if (c >= 0) { | ||
if (s) | ||
r += String.fromCharCode(a | (c >> (6 - s)) & 255); | ||
s = (s + 2) & 7; | ||
a = (c << s) & 255; | ||
} | ||
} | ||
return r; | ||
} | ||
|
||
/** | ||
* Converting a data string to a base64 encoded string | ||
* @param t data string | ||
* @return base64 encoded data string | ||
*/ | ||
function s2r(t) { | ||
var a, c, n; | ||
var r = '', l = 0, s = 0; | ||
var tl = t.length; | ||
|
||
for (n = 0; n < tl; n++) { | ||
c = t.charCodeAt(n); | ||
if (s == 0) { | ||
r += b64s.charAt((c >> 2) & 63); | ||
a = (c & 3) << 4; | ||
} else if (s == 1) { | ||
r += b64s.charAt((a | (c >> 4) & 15)); | ||
a = (c & 15) << 2; | ||
} else if (s == 2) { | ||
r += b64s.charAt(a | ((c >> 6) & 3)); | ||
l += 1; | ||
if ((l % 60) == 0) | ||
r += "\n"; | ||
r += b64s.charAt(c & 63); | ||
} | ||
l += 1; | ||
if ((l % 60) == 0) | ||
r += "\n"; | ||
|
||
s += 1; | ||
if (s == 3) | ||
s = 0; | ||
} | ||
if (s > 0) { | ||
r += b64s.charAt(a); | ||
l += 1; | ||
if ((l % 60) == 0) | ||
r += "\n"; | ||
r += '='; | ||
l += 1; | ||
} | ||
if (s == 1) { | ||
if ((l % 60) == 0) | ||
r += "\n"; | ||
r += '='; | ||
} | ||
|
||
return r; | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
Oops, something went wrong.