Title : Digital Certificates
Author : Yggdrasil
---[ Phrack Magazine Volume 8, Issue 52 January 26, 1998, article 15 of 20
-------------------------[ Technical Guide to Digital Certification
--------[ Yggdrasil
Introduction
~~~~~~~~~~~~
Today's software technology provides not only flexible controls for web pages
and complex remote interaction (ActiveX controls, Java applets and Netscape
plugins) but also offers the possibility of downloading pieces of code for
local execution to extend browsers capabilities. A major issue being the
fact that this code cannot be initially distinguished from malicious code
(virii/trojans, "man in the middle" attacks, forced downgrade, forgery of
electronic documents, etc), disguised as utilities.
The point is that end users do not know who published of a piece of software,
if the code has been tampered with, and what that software will do, (until they
download and execute it). Anyone can create plugins, applets or controls
containing this potentially destructive code or even "intelligent" malevolent
code, able to communicate covertly with a remote server.
Public-key cryptography has produced a number of different implementations
to verify the authenticity of software, network objects, documents and data
transactions (for example, Electronic Funds Transfer) using Digital IDs.
Authenticode Certifications
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Microsoft recently adopted Authenticode technology to sign their ActiveX
based software. Any individual or commercial software publisher desiring
their code to be "trusted" must apply for and receive a Digital Certificate
from an Authenticode Certificate Authority (CA), such as VeriSign. The CA
will request proof-of-identity, and other information, only then will they
verify the publishers credentials (even employing Dun & Bradstreet rating).
After the CA has decided that the publisher meets its policy criteria, it
releases a Certificate (the expected cost is about $500 for a year, plus
additional costs for hardware storage for commercial developers, up to
$12,000).
[ God save the next-generation developers. ]
A Digital Certificate contains the publishers public-key (and other info)
encrypted according to the industry standard X.509 V3 certificate format and
PKCS #7 signed data standards.
The ITU-T recommendation for X.509 states that:
"It would be a serious breach of security if the CA issued a certificate for
a user with a public key that had been tampered with."
All Certificates have an expiration time, but the CA may revoke them prior
to that time if a publisher's private-key or CA's certificate is assumed to
be compromised. The CA may (or may NOT) inform the owner of the certificate.
Revocation Lists
~~~~~~~~~~~~~~~~
The Revocation Lists, also called "black-lists", are held within entries as
attributes of types CertificateRevocationList and AuthorityRevocationList.
Their attribute types are defined as follows:
certificateRevocationList ATTRIBUTE ::= {
WITH SYNTAX CertificateList
EQUALITY MATCHING RULE certificateListExactMatch
ID id-at-certificateRevocationList }
authorityRevocationList ATTRIBUTE ::= {
WITH SYNTAX CertificateList
EQUALITY MATCHING RULE certificateListExactMatch
ID id-at-authorityRevocationList }
CertificateList ::= SIGNED { SEQUENCE {
version Version OPTIONAL,
signature AlgorithmIdentifier, <----+
issuer Name, |
thisUpdate UTCTime, |
nextUpdate UTCTime OPTIONAL, version 2
revokedCertificates SEQUENCE OF SEQUENCE { only
userCertificate CertificateSerialNumber, (extension)
revocationDate UTCTime, |
crlEntryExtensions Extensions OPTIONAL } OPTIONAL, |
crlExtensions [0] Extensions OPTIONAL }} <----+
Implementation of X.509-3
~~~~~~~~~~~~~~~~~~~~~~~~~
The ITU-T X.509 Directory Specification makes use of a set of cryptographic
systems known as asymmetric Public-Key Crypto-Systems (PKCS). This system
involves the use of two keys (one secret and one public as used in common
public key packages like PGP).
Both keys can be used for encoding: the private key to decipher if the
public key was used, and vice versa (Xp*Xs = Xs*Xp, where Xp/Xs are the
key-encoding/decoding functions).
When applied to Digital Signatures, the public key encryption is used to
encipher the data to be signed after it's passed through a hash function.
Information is signed by appending to it an enciphered summary of the info.
The summary is produced by means of a one-way hash function, while the
enciphering is carried out using the private key of the signer.
For further information about X.509 and certificate types please read
the ITU-T Recommendation X.509 ("The Directory: Authentication Framework").
Windows Trust API
~~~~~~~~~~~~~~~~~
To ascertain an objects reliability under Win32, the WinVerifyTrust() API
function is used, according to its prototype as follows:
HRESULT --------------- Description ---------------
WINAPI
WinVerifyTrust (
HWND hwnd, <>0 to allow user to assist in trust decision
DWORD dwTrustProvider, 0 = provider unknown, 1 = software publisher
DWORD dwActionID, specifies what to verify
LPVOID ActionData information required by the trust provider
)
The HRESULT return code will be TRUST_E_SUBJECT_NOT_TRUSTED if the object
is not trusted (according to the specified action in dwActionID). An error
code more detailed than this could be provided by the trust provider.
Creation of a Digitally Signed message
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PKCS #7 specifies several "types", such as ContentInfo, SignedData and
SignerInfo. Version 1.5 of PKCS #7 describes the ContentInfo type as:
ContentInfo ::= SEQUENCE {
contentType ContentType,
content
[0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
ContentType ::= OBJECT IDENTIFIER
the content is (or better: MAY be) an octet-stream ASCII string to be passed
to the selected digest algorithm (an example is MD2, see RFC-1321).
The first step is to encode the ContentInfo field according to PKCS #7.
This is the resulting encoded data:
== DATA BLOCK #1 ==
{30 28} 06 09 0x0609: contentType = data
2A 86 48 86 F7 0D 01 07 01 PKCS #7 data-object ID
A0 1B [0] EXPLICIT
04 [msg_len] content = OCTET STRING
[octet stream representing
the ASCII string, msg_len bytes long] <-- value (*)
This (*) data is the input stream to the encoding algorithm (MD2 or other):
(the identifier of the PKCS #7 data object is {1 2 840 113549 1 7 1})
== DATA BLOCK #2 ==
{30 20} 30 0C 0x300C: digestAlgorithm
06 08 2A 86 48 86 F7 0D 02 02 algorithm ID = MD2
05 00 parameters = NULL (0x00)
04 [block_len] digest
[encoded data (MD2 output)]
(the object identifier of the MD2 algorithm is {1 2 840 113549 2 2})
This data is the encoded DigestInfo. It will be encrypted under RSA using
the user's private key.
According to PKCS #1, RSA encryption has two main steps: an encryption data
block is constructed from a padding string and the prefixed message digest;
then the encryption block is exponentiated with the user's private key.
The encryption block EB is the following 64-octet string:
00 01 block type
FF FF FF FF FF FF FF FF FF FF FF FF FF FF padding string
FF FF FF FF FF FF FF FF FF FF FF FF FF
00 separator (0x00)
[here goes the whole DATA BLOCK #2] data bytes (prf. message digest)
Now we need to encode various information: a SignedData value from the inner
ContentInfo value, then the encrypted message digest, the issuer and serial
number of the user's certificate, the certificate data, the message digest
algorithm ID (MD2) and the encryption algorithm ID (PKCS #1 RSA).
The encoded SignedData is:
== DATA BLOCK #3 ==
30 82 02 3D
02 01 01 version = 1
31 [size of inner data block] digestAlgorithms
30 [size]
06 08 2A 86 48 86 F7 0D 02 02 algorithm ID = MD2
05 00 parameters = NULL (0x00)
[ContentInfo data] content = inner ContentInfo
A0 82 01 [size] certificates
[certificate data] user's certificate
31 81 [size] signerInfos
30 81 [size]
02 01 01 version = 1
30 [size] issuerAndSerialNumber
[issuer data] issuer
02 04 {12 34 56 78} size (4), serialNumber (12345678)
30 [alg_size] digestAlgorithm
06 08 2A 86 48 86 F7 0D 02 02 algorithm ID = MD2
05 00 parameters = NULL (0x00)
30 [dig_size] digestEncryptionAlgorithm
06 [sz] rsaEncryption (d.E.A.)
2A 86 48 86 F7 0D 01 01 01
05 00 parameters = NULL (0x00)
04 [data_size] encryptedDigest
[encrypted digestInfo encoded data block]
Finally, a ContentInfo value from this SignedData data block is encoded (once
again, using PKCS #7):
30 82 02 [size]
06 09 2A 86 48 86 F7 0D 01 07 02 contentType = signedData
A0 82 02 [size] [0] EXPLICIT
[here goes the whole DATA BLOCK #3] content = SignedData value
(the object identifier of PKCS #7 signedData is {1 2 840 113549 1 7 2})
PKCS Key Example
~~~~~~~~~~~~~~~~
The following is the full hex dump of the above PKCS #7 encoded key.
HEX Dump -------------------------------------: ASCII Dump ----:
30 82 02 50 06 09 2A 86 48 86 F7 0D 01 07 02 A0 0..P..*.H.......
82 02 41 30 82 02 3D 02 01 01 31 0E 30 0C 06 08 ..A0..=...1.0...
2A 86 48 86 F7 0D 02 02 05 00 30 28 06 09 2A 86 *.H.......0(..*.
48 86 F7 0D 01 07 01 A0 1B 04 19 41 20 64 65 6D H..........A dem
6F 20 43 6F 6E 74 65 6E 74 49 6E 66 6F 20 73 74 o ContentInfo st
72 69 6E 67 A0 82 01 5E 30 82 01 5A 30 82 01 04 ring...^0..Z0...
02 04 14 00 00 29 30 0D 06 09 2A 86 48 86 F7 0D .....)0...*.H...
01 01 02 05 00 30 2C 31 0B 30 09 06 03 55 04 06 .....0,1.0...U..
13 02 55 53 31 1D 30 1B 06 03 55 04 0A 13 14 45 ..US1.0...U....E
78 61 6D 70 6C 65 20 4F 72 67 61 6E 69 7A 61 74 xample Organizat
69 6F 6E 30 1E 17 0D 39 32 30 39 30 39 32 32 31 ion0...920909221
38 30 36 5A 17 0D 39 34 30 39 30 39 32 32 31 38 806Z..9409092218
30 35 5A 30 42 31 0B 30 09 06 03 55 04 06 13 02 05Z0B1.0...U....
55 53 31 1D 30 1B 06 03 55 04 0A 13 14 45 78 61 US1.0...U....Exa
6D 70 6C 65 20 4F 72 67 61 6E 69 7A 61 74 69 6F mple Organizatio
6E 31 14 30 12 06 03 55 04 03 13 0B 41 20 64 65 n1.0...U....A de
6D 6F 20 55 73 65 72 30 5B 30 0D 06 09 2A 86 48 mo User0[0...*.H
86 F7 0D 01 01 01 05 00 03 4A 00 30 47 02 40 0A .........J.0G.@.
66 79 1D C6 98 81 68 DE 7A B7 74 19 BB 7F B0 C0 fy....h.z.t.....
01 C6 27 10 27 00 75 14 29 42 E1 9A 8D 8C 51 D0 ..'.'.u.)B....Q.
53 B3 E3 78 2A 1D E5 DC 5A F4 EB E9 94 68 17 01 S..x*...Z....h..
14 A1 DF E6 7C DC 9A 9A F5 5D 65 56 20 BB AB 02 ....|....]eV ...
03 01 00 01 30 0D 06 09 2A 86 48 86 F7 0D 01 01 ....0...*.H.....
02 05 00 03 41 00 45 1A A1 E1 AA 77 20 4A 5F CD ....A.E....w J_.
F5 76 06 9D 02 F7 32 C2 6F 36 7B 0D 57 8A 6E 64 .v....2.o6{.W.nd
F3 9A 91 1F 47 95 DF 09 94 34 05 11 A0 D1 DF 4A ....G....4.....J
20 B2 6A 77 4C CA EF 75 FC 69 2E 54 C2 A1 93 7C .jwL..u.i.T...|
07 11 26 9D 9B 16 31 81 9B 30 81 98 02 01 01 30 ..&...1..0.....0
34 30 2C 31 0B 30 09 06 03 55 04 06 13 02 55 53 40,1.0...U....US
31 1D 30 1B 06 03 55 04 0A 13 14 45 78 61 6D 70 1.0...U....Examp
6C 65 20 4F 72 67 61 6E 69 7A 61 74 69 6F 6E 02 le Organization.
04 14 00 00 29 30 0C 06 08 2A 86 48 86 F7 0D 02 ....)0...*.H....
02 05 00 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 ...0...*.H......
05 00 04 40 05 FA 6A 81 2F C7 DF 8B F4 F2 54 25 ...@..j./.....T%
09 E0 3E 84 6E 11 B9 C6 20 BE 20 09 EF B4 40 EF ..>.n... . ...@.
BC C6 69 21 69 94 AC 04 F3 41 B5 7D 05 20 2D 42 ..i!i....A.}. -B
8F B2 A2 7B 5C 77 DF D9 B1 5B FC 3D 55 93 53 50 ...{\w...[.=U.SP
34 10 C1 E1 E1 4....
Many other demo (not only ;) keys, tons of related C++ source/libraries for
Linux and Win32 and documentation can be found on my web site at this address
(case sensitive):
http://members.tripod.com/~xception_0x0A28/penumbra.html
"That which does not kill us
makes us stronger"
-- Friedrich Nietzsche
----[ EOF