
In symmetric (conventional) cryptography, the same key is used for both encryption
and decryption. Public key cryptography, on the other hand,
uses a pair of keys, usually
referred to as a public key and private key.
A private key is a function
of two large prime numbers, and the corresponding public key is a function
of the product of these numbers (also known as modulus.) Although the two keys
are mathematically related it is computationally infeasible to deduce one from the other.
While the private key must be kept secret, the public key can be made available to anyone.
The most commonly used public key cryptography algorithm is RSA.
A message encrypted with a public key can only be decrypted by the corresponding
private key. The opposite is also true: if a message is encrypted by a private key
it can only be decrypted by the corresponding public key.
Under the first scenario, Alice can encrypt a message with Bob's public key
and send it to Bob. No one else but Bob can read the message as only he
has the required private key. Therefore, Alice can
use public key cryptography to send encrypted messages to Bob.
Under the second scenario, Alice can encrypt a message using her private key.
Bob can only decrypt this message using Alice's public key, so he knows the
message must have been sent by Alice.
Therefore, Alice can use public key cryptography to create digital signatures.
Since public key algorithms are extremely slow, it is not practical
to encrypt the entire message using one's public or private key. When
sending an encrypted message, the message is encrypted with a random symmetric key
and it is that symmetric key that gets encrypted using the recipient's public key
and bundled with the message. When
creating a digital signature, a oneway hash is computed from the message
and it is the hash value that gets encrypted with the sender's private key.
An instance of the CryptoHash object is always created via the CryptoContext
object's CreateHash method. As discussed earlier, CryptoContext is associated with a certain key container which usually
contains two key pairs, Key Exchange key and Signature key.
The CryptoHash object offers a method, Sign, which encrypts
the underlying hash value with one of the two private keys associated with this
hash object's cryptographic context. This method accepts a Boolean argument.
If it is set to True, the key exchange key is used. Otherwise the signature key is used.
The Sign method returns a CryptoBlob object containing the encrypted blob.
The following code snippet creates a digital signature for a file:
<!METADATA TYPE="TypeLib" UUID="{B72DF06328A411D3BF19009027438003}">
<%
Set CM = Server.CreateObject("Persits.CryptoManager")
Set Context = CM.OpenContext("mycontainer", True )
Set Hash = Context.CreateHash
Hash.AddFile "d:\somefile.txt"
Set Blob = Hash.Sign( True )
HexValue = Blob.Hex
' Export public key to file
Set Key = Context.GetUserKey( True )
Key.ExportToFile Nothing, "d:\public.key", cbtPublicKeyBlob
%>

The last line exports the corresponding public key to a file. Notice that the ExchangeKey argument of the ExportToFile method
is set to Nothing as no encryption is needed when exporting public keys.
The signature verification process goes as follows:
1. Decrypt the signature using the signer's public key.
2. Compute your own hash value of the file or message.
3. Compare values obtained in Steps 1 and 2. If they match the signature is verified.
To validate a signature with AspEncrypt, use CryptoHash's VerifySignature method which
accepts two arguments: a CryptoBlob object containing the signature
being verified and a CryptoKey object containing a public key
that corresponds to the private key used to create the signature. This method returns True if the signature is
verified, and False otherwise. To verify the Hex value created by the code snippet above,
you may use the following code:
<%
Set CM = Server.CreateObject("Persits.CryptoManager")
Set Context = CM.OpenContext("mycontainer", True )
Set Hash2 = Context.CreateHash
Hash2.AddFile "d:\somefile.txt"
Set Blob2 = CM.CreateBlob
Blob2.Hex = HexValue
Set Key2 = Context.ImportKeyFromFile( Nothing, "d:\public.key", 0 )
If Hash2.VerifySignature(Blob2, Key2 ) Then
Response.Write "Signature validated."
Else
Response.Write "Signature not validated."
End If
%>

The previous examples assume that the key pair being used to
create and verify a signature is located in an arbitrary key container.
To verify a signature, we had to export the public key into a file and transfer it
to a location where verification takes place.
In real world, public keys usually "live" inside digital certificates.
Although certificate management functionality will be covered in detail in the next section,
we are still going to show you what the signature creation and verification code
may look like when certificates are involved. These snippets below will make much more sense
once you learn more about certificates and certificate stores in the next sections.
The following code obtains a certificate by its serial number from a certificate store, and uses its private key context
to create the hash object. This way signing will be performed using this
certificate's private key:
<%
Set CM = Server.CreateObject("Persits.CryptoManager")
Set Store = CM.OpenStore("MY", True)
' obtain certificate by its serial number from store
Set Cert = Store.Certificates("F56C 31F6 0B4F 7D82 4D01 05A7 334E 2B1C")
' obtain private key context corresponding to this certificate
Set Context = Cert.PrivateKeyContext
' We are signing a text string this time
Set Hash = Context.CreateHash
Hash.AddText "some text"
Set Blob = Hash.Sign(True)
Response.Write Blob.Hex
%>

Naturally, the corresponding verification process involves the certificate's
public key. We no longer need to send the public key separately to the
verifying party. Instead, we can send the certificate itself in a file with the
extension .cer.
The Certificate Manager application which comes with IE5 will help you export
the signing certificate to a .cer file. You can also do it programmatically
using the method Cert.ExportToFile.
Here is the certificatebased signature verification code:
<%
Set CM = Server.CreateObject("Persits.CryptoManager")
Set Cert = CM.ImportCertFromFile("c:\mycert.cer")
' extract public key from this certificate
Set Context = CM.OpenContext("mycontainer", True)
Set Key = Context.ImportKeyFromCert(Cert)
' recreate hash
Set Hash = Context.CreateHash
Hash.AddText "some text"
' Populate blob object with value obtained from signing
Set Blob = CM.CreateBlob
Blob.Hex = <signature value in Hex format>
If Hash.VerifySignature(Blob, Key) Then
Response.Write "Signature validated."
Else
Response.Write "Signature not validated."
End If
%>

We use public keys to verify signatures or encrypt messages.
But how can we be sure that the owner of the public key is who we think it is?
The short answer is: we can't. For a public key cryptography
system to function, an independent trusted third party is needed
to bundle people's names and addresses with their public keys and
sign the bundle with its own private key. Such parties are called Certification Authorities (CA)
and the signed packages that contain people's personal info and public keys are called
digital certificates (or digital IDs), which is the topic of the next section.




