Asymmetric ciphers -- HowTo

How do I use the asymmetric cryptographic framework?

The asymmetric cryptographic framework consists of the following logically separate concepts:

  1. Key storage classes (For instance, CRSAPublicKey , CDSAPrivateKey )

  2. Cipher transformation classes ( CRSAPKCS1v15Encryptor , CDSASigner )

  3. Signature representative classes ( CRSASignature , CDSASignature )

The first and third are simply containers for their respective concepts. Each implementation of item two is responsible for performing one of the four primitive operations on some data using a key specified at construction. If the operation is signing or verification, then the transformation outputs a signature representative class. On the other hand, in the case of encryption or decryption, input and output consist of binary descriptor data.

Before showing some example code, an important note about object ownership. In general, unless otherwise stated, the following three rules apply.

  1. All key storage and signature representative constructors take ownership of objects given to them (typically RInteger s).

  2. All cipher transformation classes only use objects given to them (typically key storage classes, signature representatives, and descriptors).

  3. Any functions that return pointers to objects (typically the Signer classes) transfer ownership of the returned object to the caller.

Sample code for encryption/decryption

The following code illustrates how to encrypt data using an RSA PKCS#1 v1.5 encryptor. It assumes you already have access to the CRSAPublicKey you wish to encrypt to.

       
        
       
       CRSAPKCS1v15Encryptor* encryptor = CRSAPKCS1v15Encryptor::NewLC(rsaPublicKey);
//As per rules described above, encryptor does not own rsaPublicKey
HBufC8* encryptedMessage = HBufC8::NewLC(encryptor->MaxOutputLength());
encryptor->EncryptL(messageToEncrypt, *encryptedMessage);
CleanupStack::Pop(encryptedMessage);
CleanupStack::PopAndDestroy(encryptor);
      

To subsequently decrypt, again presuming access to a CRSAPrivateKey .

       
        
       
       CRSAPKCS1v15Decryptor* decryptor = CRSAPKCS1v15Decryptor::NewLC(rsaPrivateKey);
//As per rules described above, decryptor does not own rsaPrivateKey
HBufC8* decryptedMessage = HBufC8::NewLC(decryptor->MaxOutputLength());
encryptor->EncryptL(*decryptedMessage, *encryptedMessage);
CleanupStack::Pop(decryptedMessage);
CleanupStack::PopAndDestroy(decryptor);
      

Sample code for signing/verifying

All implemented signature systems (both signing and verifying) do not perform any manipulation of the input message prior to performing their internal signing mechanism. For instance, both CRSAPKCS1v15Signer and CDSASigner do not hash the data to be signed prior to signing it. Some people refer to this as a "raw sign primitive". The decision to operate this way was taken because large numbers of higher level standards dictate different ways for the data to be hashed prior to signing (and similarly for verification) and accomadating all of them significantly confused the api. Instead it is suggested a class that handles specification specific (for example, RSA signatures for TLS or X.509), pre-signing transformation is created. Upon calling a Final() -like call on such a class, it shall return a descriptor that can be "raw signed" by the implemented signing primitives.

The following code illustrates how to DSA sign an unhashed descriptor, messageToBeSigned given a CDSAPrivateKey . In this case, the pre-signing transformation required by the DSA is simply a SHA-1 hash. As a result, CSHA1 is used as the specification specific, pre-signing transformation class.

       
        
       
       CDSASigner* signer = CDSASigner::NewLC(dsaPrivateKey);
//As per rules described above, signer does not own dsaPrivateKey
CSHA1* sha1 = CSHA1::NewLC();
CDSASignature* signature = signer->SignL(sha1->Final(messageToBeSigned));
//Caller owns signature as per rules described above.
CleanupStack::PopAndDestroy(2, signer); //sha1, signer
CleanupStack::PushL(signature);
      

To subsequently verify given a CDSAPublicKey and a CDSASignature :

       
        
       
       CDSAVerifier* verifier = CDSAVerifier::NewLC(dsaPublicKey);
//As per rules described above, verifier does not own dsaPublicKey
CSHA1* sha1 = CSHA1::NewLC();
TBool result = verifier->VerifyL(sha1->Final(messageToBeVerified), *signature);
CleanupStack::PopAndDestroy(2, verifier); //sha1, verifier