Video Screencast Help
Symantec to Separate Into Two Focused, Industry-Leading Technology Companies. Learn more.
Encryption Blog

Using PGP to Secure Web Application Data-Part II

Created: 12 Aug 2008 • Updated: 05 Nov 2012
Doug McLean's picture
0 0 Votes
Login to vote

Decryption Without Key Present

The PGPsdk has a feature that allows the Encrypted Session Key (ESK) from a message to be extracted and decrypted separately. The decrypted ESK could then be used later to decrypt the original message. It works as follows:

1) Assuming the client has a PGP encrypted message.  The PGPDecode() function could be called with a event handler that extracts the ESK(s) which are presented to the handler during a  kPGPEvent_PassphraseEvent.

typedef struct
{
   PGPByte   *sessionKey;
   PGPSize   sessionKeySize;
} SessionKeyInfo;

 

static PGPError sExtractESKHandler( PGPContextRef context,
                                    PGPEvent *event,
                                    PGPUserValue userValue)
{
    PGPError            err             = kPGPError_NoErr;
    SessionKeyInfo*     info = (SessionKeyInfo*)userValue;
    switch (event->type)
    {
        case kPGPEvent_PassphraseEvent:
        {
            PGPEventPassphraseData  *d = &event->data.passphraseData;
            info->sessionKey = PGPNewData( PGPPeekContextMemoryMgr(context),
                                           d->ESKsLength,
                                           kPGPMemoryMgrFlags_None);
            CKNULL(info->sessionKey);
            info->sessionKeySize = d->ESKsLength;
            memcpy(info->sessionKey, d->ESKs, d->ESKsLength);
            break;
        }
        default:
            break;
    }
done:
    return err;
}
...
SessionKeyInfo eskInfo;
err = PGPDecode( context,
        PGPOInputBuffer ( context, cBuf, cBufSize ),
        PGPOEventHandler( context, sExtractESKHandler, & eskInfo),
        PGPOLastOption  ( context ) );

2) The ESK could be sent to a PGP Universal server as part of a user session. The universal server maintains a copy of the user decryption key (SKM/SCKM). The server would then call the PGPDecode() function using the PGPOAllowBareESKs() option, passing in the ESK.  The ESK would be decrypted and  extracted by  it's event handler at kPGPEvent_DecryptionEvent.   The server then sends the decrypted Session Key back to the client (over an encrypted link)

typedef struct
{
   PGPByte   *sessionKey;
   PGPSize   sessionKeySize;
} SessionKeyInfo;
static PGPError sDecryptESKHandler( PGPContextRef context,
                                    PGPEvent *event,
                                    PGPUserValue userValue)
{
    PGPError            err             = kPGPError_NoErr;
    SessionKeyInfo*     info = (SessionKeyInfo*)userValue;
    switch (event->type)
    {
        case kPGPEvent_DecryptionEvent:
        {
            PGPEventDecryptionData  *d = &event->data.decryptionData;
            info->sessionKey = PGPNewSecureData( PGPPeekContextMemoryMgr(context),
                                                 d->sessionKeyLength,
                                                 kPGPMemoryMgrFlags_None);
            CKNULL(info->sessionKey);
            info->sessionKeySize = d->sessionKeyLength;
            memcpy(info->sessionKey, d->sessionKey, d->sessionKeyLength);
            break;
        }
        default:
            break;
    }
done:
    return err;
}
...
SessionKeyInfo eskInfo;
SessionKeyInfo skInfo;
err = PGPDecode( context,
        PGPOInputBuffer( context, eskInfo.sessionKey, eskInfo.sessionKeySize),
        PGPOAllowBareESKs( context, TRUE),
        PGPOEventHandler( context, sDecryptESKHandler, &skInfo),
        PGPOPassphrase( context, kAlicesPassPhrase),
        PGPOKeyDBRef( context, keyDB),
        PGPOLastOption( context ) );
3) The client  decrypts the original message using PGPDecode() and specifying the decrypted session key with PGPOSessionKey() option.
SessionKeyInfo skInfo;
err = PGPDecode( context,
        PGPOInputBuffer( context, cBuf, cBufSize ),
        PGPOSessionKey( context, skInfo.sessionKey, skInfo.sessionKeySize),
                PGPOAllocatedOutputBuffer( context, &dBuf, MAX_PGPSize, &dBufSize)
        PGPOPassphrase(context, kAlicesPassPhrase),
        PGPOKeyDBRef(context, keyDB),
        PGPOLastOption( context ) );

The sum of the parts... It is possible to combine the various ideas presented in these two blogs to produce several useful products. Here are some possibilities: PGP web client building block callable by JavaScript. PGP Firefox overlay for specific web applications such as Gmail, calender, etc. JavaScript only implementation that requires no keys to be present on the client Whether they would stand alone or be part of PGP Desktop or next generation of Satellite is a matter of packaging.