The advent of public high-grade encryption in the last decade or so has given rise to programs such as Pretty Good Privacy (PGP) by Phil Zimmerman. Such programs give users access to encryption, public-key encryption, and authentication services.
A document is authenticated by virtue of a signature. The signature is a binary number (typically at least 200 bits long) that contains a cryptographic hash of the contents of the document along with information about the indentity of the person who signed the document. A hash is a mathematical value computed from all the bytes composing the document file, something like a sum, only more complex. A simple arithmetic sum is relatively easy to fake by substituting certain bytes for the bytes in the original document, while a hash function is considered too computationally difficult to fake. What this means is that the cryptographic signature for a signed document is practically impossible to forge. This also means that it is very easy to detect changes made to a document, because the hash value created from the changed document will not match the original signature.
A document signature can be contained in the the document file itself, which is usually the case for text-based documents such as ASCII or HTML files; the signature is typically appended to the end of the file. For non-text files, such as graphic images or executable binary object files, the signature is usually kept in a separate file.
PGP allows users to sign a file, producing a signature in printable ASCII form. Since this signature text contains the original document text, it can be used in place of the original document.
The example below illustrates this. It is a small ASCII text file that has been signed. The result of the signing process is the file shown below (the PGP signature is displayed as red text):
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 This is a simple text document, which is used to illustrate the concept of signing simple text files. There are no control characters or special formatting commands in this text, just simple printable ASCII characters. To make this a slightly less uninteresting document, there follows a short shopping list. eggs, 1 doz milk, 1 gal bacon, 1 lb olive oil bread, 1 loaf That's all there is to this document. -----BEGIN PGP SIGNATURE----- Version: PGPfreeware 5.5.5 for non-commercial use <http://www.nai.com> iQA/AwUBN78ib3S9RCOKzj55EQKqDACg1NV2/iyPKrDlOVJvJwz6ArcQ0UQAnjNC CDxKAFyaaGa835l1vpbFkAJk =3r/N -----END PGP SIGNATURE----- |
When the text file above is decrypted/verified, the PGP program extracts the authentication signature from the text, recomputes a new hash signature from the text, and then compares the two signatures. If the computed hash agrees with the authentication signature in the text, the text is known to be authentic.
If the signatures do not match, the text file contents do not match the contents of the original file that was signed. This indicates that the file has been either corrupted unintentionally or changed on purpose (forged).
PGP displays the results of the comparison in a PGPlog window:
The PGPlog window displays the user-ID of the person who signed the document and the date and time that the signing took place. The Validity column contains a green diamond icon, which indicates that the authentication signature is valid.
PGP will also display a text viewer window containing the clipboard contents, stripped of the signature:
It is not necessary to sign the entire text file; you can simply sign only the portion that you feel needs to be authenticated. In fact, you can sign multiple portions of the same file, and they don't need to be signed with the same key.
This is a simple text document which contains portions that are signed and portions that are not signed. The following shopping list is the only portion of this text file that is signed. -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 eggs, 1 doz milk, 1 gal bacon, 1 lb olive oil bread, 1 loaf -----BEGIN PGP SIGNATURE----- Version: PGPfreeware 5.5.5 for non-commercial use <http://www.nai.com> iQA/AwUBN796yXS9RCOKzj55EQIJDwCg9joi+YSu5D4sePwJyD2ymbdouKgAn186 4b+S1YnwRvBVAkWHNlXqIrL/ =RZgR -----END PGP SIGNATURE----- The rest of this document is not signed. |
Signing HTML documents is a little more tricky than signing simple ASCII text files, because you have to be careful about what kind of text you put into the file, or else the extra text will end up being displayed when the document is rendered by an HTML browser (which is probably not what you wanted). You want to embed the textual contents of a signature in the HTML document, but you want that extra text to be invisible when the document is displayed.
The trick is to embed the signature lines within an HTML comment entity, so that browsers will ignore them. An HTML comment begins with a <!-- and ends with a -->. Any characters may be placed between these two delimiters (except, of course, for the ending delimiter itself).
So when you sign an HTML document, you first provide a comment wrapper to surround the lines of your signature. You then sign the contents of the document excluding the leading and trailing comment delimiters.
There is one other thing you must be careful of. PGP generates its signature text so that is starts with dashes (-----) in the left margin. So that it does not get confused during the decryption/verification process, it changes all instances of a dash occurring in the left margin into a space dash sequence. This could alter the appearance of your HTML document, so the best thing to do is avoid placing any dashes in the left margin of your document.
The following example HTML document contains a PGP authentication signature (the PGP signature text is displayed in red and the enclosing comments are displayed in blue):
<!-- This is a PGP signed document -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 -- Signed by <david@tribble.com> 8ACE3E79 --> <html> <head> <title> Example Signed Document </title> </head> <body> <p> This HTML document contains a PGP authentication signature. The signature is contained within HTML comment tags so that it does not show up when the document is displayed by a browser. <p> If any part of the document between the BEGIN PGP SIGNED MESSAGE and the BEGIN PGP SIGNATURE lines is changed, the signature will not longer be valid. </body> </html> <!-- PGP authentication signature -- -----BEGIN PGP SIGNATURE----- Version: PGPfreeware 5.5.5 for non-commercial use <http://www.nai.com> iQA/AwUBN79z7HS9RCOKzj55EQJCNwCeNPOFDleAyBQV7oOsGuW+5ls7SCoAn1kw L/p/l5qmGZaU/VdhiS4CHzcQ =ebbq -----END PGP SIGNATURE----- --> |
As you can see, the contents of the document between the opening <html> and closing </html> tags is not changed in any way. The signature text, both at the head of the document and at the tail, is placed between comment delimiters. You will also notice that all leading dashes, except for those occurring in the signature text, are preceded by a space so that the signing process does not alter them.
When rendered by an HTML browser, the document above looks like this:
Example Signed Document |
This HTML document contains a PGP authentication signature. The signature is contained within HTML comment tags so that it does not show up when the document is displayed by a browser. If any part of the document between the BEGIN PGP SIGNED MESSAGE and the BEGIN PGP SIGNATURE lines is changed, the signature will not longer be valid. |
This is a snapshot of the same file as shown in a typical browser window:
You will notice that none of the PGP signature text is visible in the rendered text. This works as expected because the signature text is embedded as HTML comment entities and so therefore is ignored by browsers.
For another example of signed HTML text, look at the source for this HTML document.
The same technique of signing HTML documents can be used for signing program source code. The same trick of embedding the authentication signature text within comments is employed.
The following example source code illustrates this technique for a C/C++ program:
/*** This is a PGP signed document *** -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 *** Signed by <david@tribble.com> 8ACE3E79 ***/ /*---------------------------------------------------------------- * hello.c * The classic "hello" program. * * Written by David R. Tribble, 1999-08-20. */ #ifdef __cplusplus #include <cstdio> using namespace std; #else #include <stdio.h> #endif int main(void) { printf("Hello, world\n"); return (0); } /* End hello.c */ /*** PGP signature *** -----BEGIN PGP SIGNATURE----- Version: PGPfreeware 5.5.5 for non-commercial use <http://www.nai.com> iQA/AwUBN794c3S9RCOKzj55EQLVyQCfbr9cftls+f7M5sjlcV7a+82nYRAAnA7v k1qDSx4NJEoMsw6J1X+6EWqN =FhYx -----END PGP SIGNATURE----- ***/ |
Since the PGP signature text is enclosed within comment brackets (/* ... */), it does not affect the compilation of the program.
Note that you still must be careful to avoid placing dashes in the leftmost column, but this is not usually a problem for normal C and C++ source code.
Other programming languages allow for this kind of embedded signature text. In fact, any language that has some form of comment or remark that can span multiple source lines is capable of being signed. (Such languages include C, C++, Java, JavaScript, Pascal, PL/1, and others.)
However, some languages do not have any form of multiple-line comments, so it is problematic to embed authentication signatures in source code written in those languages. (Such languages include Ada, Eiffel, FORTRAN, COBOL, LISP, BASIC, Perl, Bourne and Korn shell, DOS batch files, assembler, and others.) A fairly workable strategy for these kinds of languages is to simply sign the entire source file, then edit the signature text by prepending the appropriate comment characters. When it comes time to decrypt/verify the signed source file, the prepended comment characters must first be removed and then the resulting text can be authenticated. It is a good idea to embed a comment describing this process immediately preceding the signature, so that future recipients of the source code understand how to properly verify it.
For example, the following Korn shell script has been signed using the technique just described:
#!/bin/ksh # Remove the leading hash marks on the next three lines for PGP verification ##-----BEGIN PGP SIGNED MESSAGE----- ##Hash: SHA1 ## #-------------------------------------------------- # copynewer # Copies one or more files into a target # directory, provided that the source # file is newer (more recent) than the # destination file. # # Usage # copynewer target-dir source-file... # # 1.0, 1999-08-22, David R. Tribble. #-------------------------------------------------- dir="$1" shift for file in "$@" do if [ "$file" -nt "$dir/$file" ] then /bin/cp "$file" "$dir" fi done # Remove the leading hash marks on the next seven lines for PGP verification ##-----BEGIN PGP SIGNATURE----- ##Version: PGPfreeware 5.5.5 for non-commercial use <http://www.nai.com> ## ##iQA/AwUBN7+NknS9RCOKzj55EQJDVgCfU68dYKh39Op8yrSPHsdhk3pKrjQAoL1+ ##0RtUyC1hrdrlo7j0ReM7d3eu ##=WHIj ##-----END PGP SIGNATURE----- # End |
Have any comments about this article?
Send email to
david@tribble.com.
Back to the author's home page at http://www.david.tribble.com.