// Copyright (c) 2002 Microsoft Corporation // // Encrypted string class // // 18 March 2002 #ifndef ENCRYPTEDSTRING_HPP_INCLUDED #define ENCRYPTEDSTRING_HPP_INCLUDED // A class that has a similar public interface as class Burnslib::String, but // is represented as an encrypted blob, produced by CryptProtectMemory. // // This class can be used to represent sensitive data like password strings // in-memory, instead of holding them as cleartext, which is a security hole // if the memory pages are swapped to disk, the machine is hibernated, etc. // // You should convert any cleartext data into an instance of this class, then // scribble out your cleartext source copy with SecureZeroMemory. class EncryptedString { public: // no string may be longer than this many characters, not including the // terminating null, or it will be truncated. static const size_t MAX_CHARACTER_COUNT = 1024 * 2 - 1; // constructs an empty string. explicit EncryptedString(); // constructs a copy of an existing, already encoded string EncryptedString(const EncryptedString& rhs); // scribbles out the text, and deletes it. ~EncryptedString() { // when the object dies, it had better not have any outstanding // cleartext copies. ASSERT(cleartextCopyCount == 0); Reset(); } // disposes of the encrypted text, and sets the string to be empty. void Clear() { // when the object dies, it had better not have any outstanding // cleartext copies. ASSERT(cleartextCopyCount == 0); Reset(); } // Scribbles out and de-allocates a clear text copy of the string. The // caller is required to balance each call to GetClearTextCopy with a call // to DestroyClearTextCopy lest he leak memory and leave cleartext hanging // around. // // cleartext - the same pointer returned by a previous call to // GetClearTextCopy on the same instance. void DestroyClearTextCopy(WCHAR* cleartext) const; // thrown by GetClearTextCopy if decryption fails. class DecryptionFailureException { public: DecryptionFailureException() { } }; // Extracts the decoded cleartext representation of the text, including // null terminator. The caller must invoke DestroyClearTextCopy on the // result, even if the result is null. // // Throws a DecryptionFailureException on failure. // // Example: // WCHAR* cleartext = encoded.GetDecodedCopy(); // if (cleartext) // { // // ... use the cleartext // } // encoded.DestroyClearTextCopy(); WCHAR* GetClearTextCopy() const; // Returns true if the string is zero-length, false if not. bool IsEmpty() const { return (GetLength() == 0); } // Sets the contents of self to the encoded representation of the // cleartext, replacing the previous value of self. The encoded // representation will be the same length, in characters, as the // cleartext. // // clearText - in, un-encoded text to be encoded. May be empty string, // but not a null pointer. void Encrypt(const WCHAR* cleartext); // Returns the length, in unicode characters, of the cleartext, not // including the null terminator. size_t GetLength() const; // Replaces the contents of self with a copy of the contents of rhs. // Returns *this. const EncryptedString& operator= (const EncryptedString& rhs); // Compares the cleartext representations of self and rhs, and returns // true if they are lexicographically the same: the lengths are the same // and all the characters are the same. bool operator== (const EncryptedString& rhs) const; bool operator!= (const EncryptedString& rhs) const { return !(operator==(rhs)); } private: void Clone(const EncryptedString& rhs); void Init(const WCHAR* clearText); WCHAR* InternalDecrypt() const; void InternalDestroy(WCHAR* cleartext) const; void Reset(); // We deliberately do not implement conversion to or from WCHAR* or // String. This is to force the user of the class to be very deliberate // about decoding the string. class String is a copy-on-write shared // reference implementation, and we don't want to make it easy to create // "hidden" copies of cleartext, or move from one representation to // another, or accidentally get a string filled with encrypted text. // deliberately commented out // explicit // EncryptedString(const String& cleartext); // deliberately commented out // operator WCHAR* (); // operator String (); size_t clearTextLength; // In the course of en[de]crypting, and assigning to the instance, we // may reallocate the memory pointed to here, but logically the string // is still "const" mutable WCHAR* cypherText; // a logically const instance may have cleartext copies made mutable int cleartextCopyCount; // indicates that the encryption worked. bool isEncrypted; }; #endif // ENCRYPTEDSTRING_HPP_INCLUDED