The asymmetric cryptographic framework consists of the following logically separate concepts:
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.
All key storage and signature representative constructors take ownership of objects given to them (typically RInteger s).
All cipher transformation classes only use objects given to them (typically key storage classes, signature representatives, and descriptors).
Any functions that return pointers to objects (typically the Signer classes) transfer ownership of the returned object to the caller.
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);
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);
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License v1.0.