Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
sources/TPGPkey.cp
// TPGPkey.cp - PGP Key Object |
// |
// Apple Macintosh Developer Technical Support |
// Written by: Vinnie Moscaritolo |
// |
// Copyright (work in progress) Apple Computer, Inc All rights reserved. |
// |
// You may incorporate this sample code into your applications without |
// restriction, though the sample code has been provided "AS IS" and the |
// responsibility for its operation is 100% yours. However, what you are |
// not permitted to do is to redistribute the source as "DSC Sample Code" |
// after having made changes. If you're going to re-distribute the source, |
// we require that you make it clear in the source that the code was |
// descended from Apple Sample Code, but that you've made changes. |
// |
#include <string.h> |
#include <TextUtils.h> |
#include <PLStringFuncs.h> |
#include "TPGPkey.h" |
#include "TPGPException.h" |
#include "pgpRandomPool.h" |
#include "pgpUserInterface.h" |
#include "pgpPublicKey.h" |
// =========================================================================== |
// Static member variables |
// =========================================================================== |
PGPContextRef TPGPkey::fgContext = kInvalidPGPContextRef; // PGP context |
PGPKeySetRef TPGPkey::fgPGPKeySetRef = kInvalidPGPKeySetRef; // this keyset |
// --------------------------------------------------------------------------- |
void TPGPkey::Initialize() // (static public) |
// --------------------------------------------------------------------------- |
// Create a new PGP context |
{ |
if(! PGPContextRefIsValid(fgContext) ) |
ThrowIfPGPErr( PGPNewContext( kPGPsdkAPIVersion, &fgContext)); |
} |
// --------------------------------------------------------------------------- |
void TPGPkey::Initialize(PGPMemoryMgrRef memMgr) // (static public) |
// --------------------------------------------------------------------------- |
// Create a ustome PGP context |
{ |
PGPNewContextStruct contextInfo; |
// Create a custom PGP context |
contextInfo.sizeofStruct = sizeof( PGPNewContextStruct ); |
contextInfo.memoryMgr = memMgr; |
if(! PGPContextRefIsValid(fgContext) ) |
ThrowIfPGPErr( PGPNewContextCustom( kPGPsdkAPIVersion, &contextInfo ,&fgContext)); |
} |
// --------------------------------------------------------------------------- |
void TPGPkey::Finalize() // (static public) |
// --------------------------------------------------------------------------- |
// shutdown a new PGP context |
{ |
if( PGPContextRefIsValid( fgContext)) PGPFreeContext(fgContext ); |
fgContext = kInvalidPGPContextRef; |
} |
// --------------------------------------------------------------------------- |
void TPGPkey::OpenKeyDefaultRing() // (static public) |
// --------------------------------------------------------------------------- |
// Create a new PGP context |
{ |
if( PGPContextRefIsValid(fgContext) |
&& ( fgPGPKeySetRef == kInvalidPGPKeySetRef) ) |
ThrowIfPGPErr( PGPOpenDefaultKeyRings(fgContext, 0, &fgPGPKeySetRef)) ; |
} |
// --------------------------------------------------------------------------- |
void TPGPkey::CloseKeyRing() // (static public) |
// --------------------------------------------------------------------------- |
// Create a new PGP context |
{ |
if( PGPContextRefIsValid(fgContext) && PGPKeySetRefIsValid ( fgPGPKeySetRef )) |
PGPFreeKeySet (fgPGPKeySetRef ); |
fgPGPKeySetRef = kInvalidPGPKeySetRef; |
} |
// --------------------------------------------------------------------------- |
void TPGPkey::Initialize(PGPKeyRef theKey) |
// --------------------------------------------------------------------------- |
// |
{ |
if( PGPContextRefIsValid(fgContext) |
/* && PGPKeySetRefIsValid(fgPGPKeySetRef) */ |
&& PGPKeyRefIsValid(theKey)) |
{ |
PGPHashContextRef theHashRef = kInvalidPGPHashContextRef; |
PGPInt32 level; |
PGPTime theTime; |
ThrowIfPGPErr( PGPGetKeyNumber (theKey, kPGPKeyPropAlgID, (PGPInt32*) &fPublicKeyAlgorithm)); |
ThrowIfPGPErr( PGPGetHashAlgUsed (theKey, &fHashAlgorithm) ); |
ThrowIfPGPErr( PGPGetKeyBoolean (theKey, kPGPKeyPropIsExpired, &fExpired)); |
ThrowIfPGPErr( PGPGetKeyBoolean (theKey, kPGPKeyPropIsRevoked, &fRevoked)); |
ThrowIfPGPErr( PGPGetKeyBoolean (theKey, kPGPKeyPropIsDisabled, &fDisabled)); |
ThrowIfPGPErr( PGPGetKeyBoolean (theKey, kPGPKeyPropIsAxiomatic,&fAxiomatic)) ; |
ThrowIfPGPErr( PGPGetKeyNumber(theKey, kPGPKeyPropBits, (PGPInt32*) &fKeySize)); |
ThrowIfPGPErr( PGPGetKeyTime(theKey, kPGPKeyPropCreation, &theTime)); |
fCreatedTime = PGPTimeToMacTime(theTime); |
ThrowIfPGPErr( PGPGetKeyTime(theKey, kPGPKeyPropExpiration, &theTime)); |
fExpireTime = PGPTimeToMacTime(theTime); |
ThrowIfPGPErr (PGPNewHashContext( PGPGetContextMemoryMgr(fgContext), fHashAlgorithm, &theHashRef)); |
ThrowIfPGPErr (PGPGetHashSize( theHashRef,&fHashSize)); |
PGPFreeHashContext(theHashRef); |
ThrowIfPGPErr( PGPGetPrimaryUserIDValidity(theKey, &fValidity)); |
ThrowIfPGPErr( PGPGetKeyNumber(theKey, kPGPKeyPropTrust, &level)); |
switch(level) |
{ |
default: |
case kPGPKeyTrust_Undefined: |
case kPGPKeyTrust_Unknown: |
case kPGPKeyTrust_Never: |
fTrustLevel = 0; |
break; |
case kPGPKeyTrust_Marginal: |
fTrustLevel = 1; |
break; |
case kPGPKeyTrust_Complete: |
fTrustLevel = 2; |
break; |
case kPGPKeyTrust_Ultimate: |
fTrustLevel = 3; |
break; |
} |
fKeyRef = theKey; |
fInitialized = true; |
} |
else |
{ |
fKeyRef = kInvalidPGPKeyRef; |
fInitialized = false; |
} |
} |
// --------------------------------------------------------------------------- |
Boolean TPGPkey::CanSign() |
// --------------------------------------------------------------------------- |
// key can be used to sign |
{ |
Boolean result = false; |
if( this->IsOperational() ) |
ThrowIfPGPErr( PGPGetKeyBoolean (fKeyRef, kPGPKeyPropCanSign, &result)); |
return result; |
} |
// --------------------------------------------------------------------------- |
Boolean TPGPkey::CanVerify() |
// --------------------------------------------------------------------------- |
// key can be used to sign |
{ |
Boolean result = false; |
if( this->IsOperational() ) |
ThrowIfPGPErr( PGPGetKeyBoolean (fKeyRef, kPGPKeyPropCanVerify, &result)); |
return result; |
} |
// --------------------------------------------------------------------------- |
short TPGPkey::GetIconID() |
// --------------------------------------------------------------------------- |
// determine which icon to draw |
{ |
short iconID = kAlertIcon_ID; |
if( fInitialized ) |
{ |
if(fPublicKeyAlgorithm == kPGPPublicKeyAlgorithm_RSA) |
{ |
if( fRevoked) iconID = kIconRSA_Revoked_ID; |
else if(fExpired) iconID = kIconRSA_Expired_ID; |
else if(fDisabled) iconID = kIconRSA_Disabled_ID; |
else iconID = kIconRSA_ID; |
} |
else if(fPublicKeyAlgorithm == kPGPPublicKeyAlgorithm_DSA) |
{ |
if(fRevoked) iconID = kIconDH_RevokedID; |
else if(fExpired) iconID = kIconDH_Expired_ID; |
else if(fDisabled) iconID = kIconDH_Disabled_ID; |
else iconID = kIconDH_ID; |
} |
} |
return iconID; |
} |
// --------------------------------------------------------------------------- |
void TPGPkey::GetPrimaryUserNamePString(StringPtr outbuf) |
// --------------------------------------------------------------------------- |
// |
{ |
PGPSize bufLen; |
char buffer[256]; |
ThrowIfPGPErr(PGPGetPrimaryUserIDNameBuffer(fKeyRef, sizeof( buffer) -1 , (char*) &buffer[1], &bufLen )); |
// truncate at email address |
buffer[0] = (strchr(&buffer[1], '<') - &buffer[1] - 1); |
PLstrcpy(outbuf,(StringPtr) buffer); |
} |
// --------------------------------------------------------------------------- |
void TPGPkey::GetFingerprintBinaryPString(void* outBuf) |
// --------------------------------------------------------------------------- |
// |
{ |
PGPSize fpSize; |
unsigned char* p = (unsigned char*) outBuf; |
ThrowIfPGPErr( PGPGetKeyPropertyBuffer( fKeyRef, kPGPKeyPropFingerprint, MAX_PGPSize, NULL, &fpSize)); |
ThrowIfPGPErr(PGPGetKeyPropertyBuffer( fKeyRef, kPGPKeyPropFingerprint, fpSize, &p[1], &fpSize)); |
p[0] = (fpSize & 0xFF); |
} |
// --------------------------------------------------------------------------- |
void TPGPkey::GetFingerprintPString(StringPtr outBuf) |
// --------------------------------------------------------------------------- |
// |
{ |
const char hexDigit[] = "0123456789ABCDEF"; |
PGPSize bufLen; |
unsigned char buffer[255]; |
int strIndex; |
ThrowIfPGPErr(PGPGetKeyPropertyBuffer( fKeyRef, kPGPKeyPropFingerprint, sizeof( buffer ), buffer, &bufLen)); |
char *p = (char *) outBuf; |
*p++ = '\0'; |
if(bufLen == 20) |
{ |
for(strIndex = 0 ; strIndex < 20 ; strIndex++) |
{ |
*p++ = hexDigit[buffer[strIndex]>>4]; |
*p++ = hexDigit[buffer[strIndex]&0xF]; |
if((strIndex == 1) || (strIndex == 3) || (strIndex == 5) |
|| (strIndex == 7) || (strIndex == 11) || |
(strIndex == 13) |
|| (strIndex == 13) || (strIndex == 15) || |
(strIndex == 17)) |
*p++ = ' '; |
else if(strIndex == 9) |
{ |
*p++ = ' '; |
*p++ = ' '; |
// *p++ = '\r'; |
} |
} |
} |
else |
{ |
for(strIndex = 0 ; strIndex < 16 ; strIndex++) |
{ |
*p++ = hexDigit[buffer[strIndex]>>4]; |
*p++ = hexDigit[buffer[strIndex]&0xF]; |
if((strIndex == 1) || (strIndex == 3) || (strIndex == 5) |
|| (strIndex == 9) || (strIndex == 11) || (strIndex == 13)) |
*p++ = ' '; |
else if(strIndex == 7) |
{ |
*p++ = ' '; |
*p++ = ' '; |
} |
} |
} |
outBuf[0] = (p - (char*)outBuf - 1) & 0xFF; |
} |
// --------------------------------------------------------------------------- |
void TPGPkey::GetPublicKeyAlgorithmPstring(StringPtr outBuf) |
// --------------------------------------------------------------------------- |
// |
{ |
StringPtr algStr = "\pUnknown"; |
if(outBuf) |
{ |
if( fInitialized ) |
switch(fPublicKeyAlgorithm) |
{ |
case kPGPPublicKeyAlgorithm_Invalid: algStr = "\pInvalid"; break; |
case kPGPPublicKeyAlgorithm_RSA: algStr = "\pRSA"; break; |
case kPGPPublicKeyAlgorithm_RSAEncryptOnly: algStr = "\pRSA (Encrypt Only)"; break; |
case kPGPPublicKeyAlgorithm_RSASignOnly: algStr = "\pRSA (Sign Only)"; break; |
case kPGPPublicKeyAlgorithm_ElGamal: algStr = "\pDiffie-Hellman"; break; |
case kPGPPublicKeyAlgorithm_DSA: algStr = "\pDSS"; break; |
} |
PLstrcpy(outBuf,algStr); |
} |
} |
// --------------------------------------------------------------------------- |
void TPGPkey::Export(void** buf, PGPSize *bufSize ) |
// --------------------------------------------------------------------------- |
// |
{ |
if( this->IsOperational() ) |
{ |
PGPKeySetRef theKeyset; |
Str255 keyName; |
this->GetPrimaryUserNamePString(keyName); |
p2cstr(keyName); |
PGPNewSingletonKeySet( fKeyRef,&theKeyset ); |
PGPExportKeySet( theKeyset, |
PGPOAllocatedOutputBuffer ( fgContext, buf, MAX_PGPUInt32, bufSize ), |
PGPOArmorOutput (fgContext, true), |
// PGPOVersionString (fgContext, "PGPUAM Version 1.0" ), |
PGPOCommentString (fgContext, (char*) keyName), |
PGPOLastOption( fgContext )); |
PGPFreeKeySet(theKeyset); |
} |
} |
// the behaviour of allowing disable keys to verify is questionable. |
// PGPTools allows a user to verify and decrypt with keys that have |
// been flagged by the user as disabled...BUT It could be argued that |
// this is the wroong thing to do in a server authentication environment |
// if disagree wit hthis feel free to disable the following define.. |
#define DISABLED_KEYS_CANT_VERIFY 1 |
// --------------------------------------------------------------------------- |
Boolean TPGPkey::Verify( void* inbuf, PGPSize inBufSize, void* sigbuf, PGPSize sigBufSize ) |
// --------------------------------------------------------------------------- |
// |
{ |
PGPError err = kPGPError_BadParams; |
if( this->IsOperational() |
#if DISABLED_KEYS_CANT_VERIFY |
&& ! this->IsDisabled() |
#endif |
) |
{ |
PGPHashContextRef theHashRef = kInvalidPGPHashContextRef; |
PGPPublicKeyContextRef thePublicKeyRef = kInvalidPGPPublicKeyContextRef; |
ThrowIfPGPErr( PGPNewHashContext( PGPGetContextMemoryMgr(fgContext), fHashAlgorithm, &theHashRef)); |
ThrowIfPGPErr( PGPContinueHash( theHashRef,inbuf, inBufSize )); |
ThrowIfPGPErr( PGPNewPublicKeyContext( fKeyRef, |
kPGPPublicKeyMessageFormat_PGP, |
&thePublicKeyRef)); |
err = PGPPublicKeyVerifySignature( thePublicKeyRef, theHashRef, sigbuf, sigBufSize) ; |
PGPFreePublicKeyContext(thePublicKeyRef); |
} |
return (err == kPGPError_NoErr) ; |
} |
// --------------------------------------------------------------------------- |
Boolean TPGPkey::Sign( void* inbuf, PGPSize inBufSize, void* sigbuf, PGPSize *sigBufSize, const char *passPhrase) |
// --------------------------------------------------------------------------- |
// |
{ |
PGPError err = kPGPError_BadParams; |
if( this->IsOperational() ) |
{ |
PGPHashContextRef theHashRef = kInvalidPGPHashContextRef; |
PGPPrivateKeyContextRef thePrivateKeyRef = kInvalidPGPPrivateKeyContextRef; |
ThrowIfPGPErr( PGPNewHashContext( PGPGetContextMemoryMgr(fgContext), fHashAlgorithm, &theHashRef)); |
ThrowIfPGPErr( PGPContinueHash( theHashRef,inbuf, inBufSize )); |
err = PGPNewPrivateKeyContext( fKeyRef, kPGPPublicKeyMessageFormat_PGP, &thePrivateKeyRef, |
PGPOPassphrase( fgContext, passPhrase), |
PGPOLastOption( fgContext )); |
if(err == kPGPError_NoErr) |
{ |
ThrowIfPGPErr( PGPPrivateKeySign( thePrivateKeyRef, theHashRef, sigbuf, sigBufSize )); |
PGPFreePrivateKeyContext(thePrivateKeyRef); |
} |
} |
return (err == kPGPError_NoErr) ; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-22