Fix ascii dearmor and signature verification bugs
This commit is contained in:
parent
b4676d2ad8
commit
f59fa54ecf
|
@ -25,8 +25,6 @@
|
||||||
*/
|
*/
|
||||||
function openpgp_encoding_deArmor(text) {
|
function openpgp_encoding_deArmor(text) {
|
||||||
text = text.replace(/\r/g, '');
|
text = text.replace(/\r/g, '');
|
||||||
// remove whitespace of blank line to allow later split at \n\n
|
|
||||||
text = text.replace(/\n\s+\n/, '\n\n');
|
|
||||||
|
|
||||||
var type = openpgp_encoding_get_type(text);
|
var type = openpgp_encoding_get_type(text);
|
||||||
|
|
||||||
|
@ -34,69 +32,99 @@ function openpgp_encoding_deArmor(text) {
|
||||||
var splittedtext = text.split('-----');
|
var splittedtext = text.split('-----');
|
||||||
// splittedtext[0] - should be the empty string
|
// splittedtext[0] - should be the empty string
|
||||||
// splittedtext[1] - should be BEGIN...
|
// splittedtext[1] - should be BEGIN...
|
||||||
// splittedtext[2] - the message and checksum
|
// splittedtext[2] - \nthe message and checksum
|
||||||
// splittedtest[3] - should be END...
|
// splittedtext[3] - should be END...
|
||||||
|
|
||||||
// chunks separated by blank lines
|
// chunks separated by blank lines
|
||||||
var splittedChunks = splittedtext[2]
|
var msg = openpgp_encoding_split_headers(splittedtext[2].slice(1));
|
||||||
.split('\n\n');
|
var msg_sum = openpgp_encoding_split_checksum(msg.body);
|
||||||
var messageAndChecksum = splittedtext[2]
|
|
||||||
.split('\n\n')[1]
|
|
||||||
.split('\n=');
|
|
||||||
|
|
||||||
var message = messageAndChecksum[0]
|
|
||||||
.replace(/\n- /g,"\n");
|
|
||||||
// sometimes, there's a blank line between message and checksum
|
|
||||||
var checksum;
|
|
||||||
if(messageAndChecksum.length == 1){
|
|
||||||
// blank line
|
|
||||||
checksum = splittedtext[2]
|
|
||||||
.replace(/[\n=]/g, "");
|
|
||||||
} else {
|
|
||||||
// no blank line
|
|
||||||
checksum = messageAndChecksum[1]
|
|
||||||
.split('\n')[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
openpgp: openpgp_encoding_base64_decode(message),
|
openpgp: openpgp_encoding_base64_decode(msg_sum.body),
|
||||||
type: type
|
type: type
|
||||||
};
|
};
|
||||||
|
|
||||||
if (verifyCheckSum(data.openpgp, checksum)) {
|
if (verifyCheckSum(data.openpgp, msg_sum.checksum)) {
|
||||||
return data;
|
return data;
|
||||||
} else {
|
} else {
|
||||||
util.print_error("Ascii armor integrity check on message failed: '"
|
util.print_error("Ascii armor integrity check on message failed: '"
|
||||||
+ checksum
|
+ msg_sum.checksum
|
||||||
+ "' should be '"
|
+ "' should be '"
|
||||||
+ getCheckSum(data) + "'");
|
+ getCheckSum(data) + "'");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var splittedtext = text.split('-----');
|
var splittedtext = text.split('-----');
|
||||||
|
// splittedtext[0] - should be the empty string
|
||||||
|
// splittedtext[1] - should be BEGIN PGP SIGNED MESSAGE
|
||||||
|
// splittedtext[2] - \nthe message
|
||||||
|
// splittedtext[3] - should be BEGIN PGP SIGNATURE
|
||||||
|
// splittedtext[4] - \nthe signature and checksum
|
||||||
|
// splittedtext[5] - should be END PGP SIGNATURE
|
||||||
|
|
||||||
|
var msg = openpgp_encoding_split_headers(splittedtext[2].slice(1));
|
||||||
|
var sig = openpgp_encoding_split_headers(splittedtext[4].slice(1));
|
||||||
|
var sig_sum = openpgp_encoding_split_checksum(sig.body);
|
||||||
|
|
||||||
var result = {
|
var result = {
|
||||||
text: splittedtext[2]
|
text: msg.body.replace(/\n\n$/, "\n").replace(/\n/g, "\r\n"),
|
||||||
.replace(/\n- /g,"\n")
|
openpgp: openpgp_encoding_base64_decode(sig_sum.body),
|
||||||
.split("\n\n")[1],
|
|
||||||
openpgp: openpgp_encoding_base64_decode(splittedtext[4]
|
|
||||||
.split("\n\n")[1]
|
|
||||||
.split("\n=")[0]),
|
|
||||||
type: type
|
type: type
|
||||||
};
|
};
|
||||||
|
|
||||||
if (verifyCheckSum(result.openpgp, splittedtext[4]
|
if (verifyCheckSum(result.openpgp, sig_sum.checksum)) {
|
||||||
.split("\n\n")[1]
|
|
||||||
.split("\n=")[1]))
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
else {
|
} else {
|
||||||
util.print_error("Ascii armor integrity check on message failed");
|
util.print_error("Ascii armor integrity check on message failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits a message into two parts, the headers and the body. This is an internal function
|
||||||
|
* @param {String} text OpenPGP armored message part
|
||||||
|
* @returns {(Boolean|Object)} Either false in case of an error
|
||||||
|
* or an object with attribute "headers" containing the headers and
|
||||||
|
* and an attribute "body" containing the body.
|
||||||
|
*/
|
||||||
|
function openpgp_encoding_split_headers(text) {
|
||||||
|
var reEmptyLine = /^[\t ]*\n/m;
|
||||||
|
var headers = "";
|
||||||
|
var body = text;
|
||||||
|
|
||||||
|
var matchResult = reEmptyLine.exec(text);
|
||||||
|
|
||||||
|
if (matchResult != null) {
|
||||||
|
headers = text.slice(0, matchResult.index);
|
||||||
|
body = text.slice(matchResult.index + matchResult[0].length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { headers: headers, body: body };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits a message into two parts, the body and the checksum. This is an internal function
|
||||||
|
* @param {String} text OpenPGP armored message part
|
||||||
|
* @returns {(Boolean|Object)} Either false in case of an error
|
||||||
|
* or an object with attribute "body" containing the body
|
||||||
|
* and an attribute "checksum" containing the checksum.
|
||||||
|
*/
|
||||||
|
function openpgp_encoding_split_checksum(text) {
|
||||||
|
var reChecksumStart = /^=/m;
|
||||||
|
var body = text;
|
||||||
|
var checksum = "";
|
||||||
|
|
||||||
|
var matchResult = reChecksumStart.exec(text);
|
||||||
|
|
||||||
|
if (matchResult != null) {
|
||||||
|
body = text.slice(0, matchResult.index);
|
||||||
|
checksum = text.slice(matchResult.index + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { body: body, checksum: checksum };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds out which Ascii Armoring type is used. This is an internal function
|
* Finds out which Ascii Armoring type is used. This is an internal function
|
||||||
* @param {String} text [String] ascii armored text
|
* @param {String} text [String] ascii armored text
|
||||||
|
@ -124,7 +152,7 @@ function openpgp_encoding_get_type(text) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
// BEGIN PGP SIGNATURE
|
// BEGIN PGP SIGNED MESSAGE
|
||||||
// Used for detached signatures, OpenPGP/MIME signatures, and
|
// Used for detached signatures, OpenPGP/MIME signatures, and
|
||||||
// cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE
|
// cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE
|
||||||
// for detached signatures.
|
// for detached signatures.
|
||||||
|
|
|
@ -130,7 +130,7 @@ function _openpgp () {
|
||||||
function read_message(armoredText) {
|
function read_message(armoredText) {
|
||||||
var dearmored;
|
var dearmored;
|
||||||
try{
|
try{
|
||||||
dearmored = openpgp_encoding_deArmor(armoredText.replace(/\r/g,''));
|
dearmored = openpgp_encoding_deArmor(armoredText);
|
||||||
}
|
}
|
||||||
catch(e){
|
catch(e){
|
||||||
util.print_error('no message found!');
|
util.print_error('no message found!');
|
||||||
|
|
|
@ -93,14 +93,14 @@ function openpgp_msg_message() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pubkey.length == 0)
|
if (pubkey.length == 0) {
|
||||||
util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(this.signature.issuerKeyId)+". Public key not found in keyring.");
|
util.print_warning("Unable to verify signature of issuer: "+util.hexstrdump(this.signature.issuerKeyId)+". Public key not found in keyring.");
|
||||||
else {
|
} else {
|
||||||
for (var i = 0 ; i < pubkey.length; i++) {
|
for (var i = 0 ; i < pubkey.length; i++) {
|
||||||
var tohash = this.text.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n");
|
if (this.signature.verify(this.text, pubkey[i])) {
|
||||||
if (this.signature.verify(tohash, pubkey[i])) {
|
|
||||||
util.print_info("Found Good Signature from "+pubkey[i].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[i].obj.getKeyId()).substring(8)+")");
|
util.print_info("Found Good Signature from "+pubkey[i].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[i].obj.getKeyId()).substring(8)+")");
|
||||||
result = true;
|
result = true;
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
util.print_error("Signature verification failed: Bad Signature from "+pubkey[i].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")");
|
util.print_error("Signature verification failed: Bad Signature from "+pubkey[i].obj.userIds[0].text+" (0x"+util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8)+")");
|
||||||
}
|
}
|
||||||
|
|
|
@ -497,14 +497,21 @@ function openpgp_packet_signature() {
|
||||||
if (this.version == 4) {
|
if (this.version == 4) {
|
||||||
this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm,
|
this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm,
|
||||||
this.MPIs, key.obj.publicKeyPacket.MPIs, data+this.signatureData+trailer);
|
this.MPIs, key.obj.publicKeyPacket.MPIs, data+this.signatureData+trailer);
|
||||||
|
} else {
|
||||||
|
this.verified = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // 0x01: Signature of a canonical text document.
|
case 1: // 0x01: Signature of a canonical text document.
|
||||||
if (this.version == 4) {
|
if (this.version == 4) {
|
||||||
|
var tohash = data
|
||||||
|
.replace(/\r\n/g,"\n")
|
||||||
|
.replace(/[\t ]+\n/g, "\n")
|
||||||
|
.replace(/\n/g,"\r\n");
|
||||||
this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm,
|
this.verified = openpgp_crypto_verifySignature(this.publicKeyAlgorithm, this.hashAlgorithm,
|
||||||
this.MPIs, key.obj.publicKeyPacket.MPIs, data+this.signatureData+trailer);
|
this.MPIs, key.obj.publicKeyPacket.MPIs, tohash+this.signatureData+trailer);
|
||||||
return this.verified;
|
} else {
|
||||||
|
this.verified = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -630,6 +637,7 @@ function openpgp_packet_signature() {
|
||||||
// document) that cannot include a target subpacket.
|
// document) that cannot include a target subpacket.
|
||||||
default:
|
default:
|
||||||
util.print_error("openpgp.packet.signature.js\n"+"signature verification for type"+ this.signatureType+" not implemented");
|
util.print_error("openpgp.packet.signature.js\n"+"signature verification for type"+ this.signatureType+" not implemented");
|
||||||
|
this.verified = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return this.verified;
|
return this.verified;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user