Click here to Skip to main content
15,895,142 members
Articles / Programming Languages / C++

Product Keys Based on the Advanced Encryption Standard (AES)

Rate me:
Please Sign up or sign in to vote.
4.97/5 (69 votes)
12 Jun 2007CPOL11 min read 301K   25.3K   352  
A Compact Product Key System Based on AES and Crypto++
// KeyGen.cpp
#include "StdAfx.h"

// Runtime Includes
#include <iostream>

// Crypto++ Includes
#include "cryptlib.h"
#include "osrng.h"      // PRNG
#include "Base32.h"     // Base32
#include "hex.h"        // Hex
#include "aes.h"        // AES
#include "modes.h"      // CBC_Mode< >
#include "filters.h"    // StringSource and
                        // StreamTransformation

// The Features Available...
const unsigned int FEATURE_EVALUATION  = 0x01;  //               0000 0001
const unsigned int FEATURE_USE_SQUARES = 0x02;  //               0000 0010
const unsigned int FEATURE_USE_CIRCLES = 0x04;  //               0000 0100
const unsigned int FEATURE_USE_WIDGETS = 0x08;  //               0000 1000
// Span Byte Boundary...
const unsigned int FEATURE_USE_ELLIPSES  = 0x0100;  // 0000 0001 0000 0000 
const unsigned int FEATURE_USE_TRIANGLES = 0x0200;  // 0000 0010 0000 0000 
const unsigned int FEATURE_USE_POLYGONS  = 0x0400;  // 0000 0100 0000 0000 
const unsigned int FEATURE_USE_PENTAGONS = 0x0800;  // 0000 1000 0000 0000 

 // 1010 1010 ... 1010 1010
const unsigned int FEATURE_MAGIC = 0xAAAAAAAA;

void PrintPrologue( std::string algorithm, byte* key, int keylen, byte* iv, int ivlen );
void EncodeFeatures( std::string& FeatureText, unsigned int features );
void PrintFeatures( unsigned int features );

int main(int argc, char* argv[]) {
    
    // Key and IV setup
    byte key[ CryptoPP::AES::DEFAULT_KEYLENGTH ] =
        { 0x93, 0x33, 0x6B, 0x82, 0xD6, 0x64, 0xB2, 0x46,
          0x95, 0xAB, 0x89, 0x91, 0xD3, 0xE5, 0xDC, 0xB0 };

    byte  iv[ CryptoPP::AES::BLOCKSIZE ] =
        { 0x61, 0x4D, 0xCA, 0x6F, 0xB2, 0x56, 0xF1, 0xDB,
          0x0B, 0x24, 0x5D, 0xCF, 0xB4, 0xBD, 0xB6, 0xD3 };

    // Pseudo Random Number Generator
    CryptoPP::AutoSeededRandomPool rng;

    // Encryptor
    CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption
        Encryptor( key, sizeof(key), iv );

    // Decryptor
    CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption
        Decryptor( key, sizeof(key), iv );

    // Magic
    const std::string MagicText( 4, (char)0xAA );

    //////////////////////////////////////////
    //                Output                //
    //////////////////////////////////////////
    
    PrintPrologue( Encryptor.AlgorithmName(), key,
                   sizeof(key), iv, sizeof(iv) );

    ///////////////////////////////////////////
    //            Generation Loop            //
    ///////////////////////////////////////////

    unsigned int ITERATIONS = 3;
    for( unsigned int i = 0; i < ITERATIONS; i++ )
    {
        std::string FeatureText = "";
        std::string SaltText = "";
        std::string EncodedText = "";
        Encryptor.Resynchronize( iv );
        Decryptor.Resynchronize( iv );

        // Salt
        CryptoPP::RandomNumberSource( rng, 4, true,
            new CryptoPP::StringSink( SaltText )
        ); // RandomNumberSource

        // Features
        //   No Longer Random
        unsigned int Features = 0;
        Features |= FEATURE_USE_ELLIPSES;
        Features |= FEATURE_USE_PENTAGONS;
        EncodeFeatures( FeatureText, Features );
            
        // Encryption
        CryptoPP::StringSource( SaltText + MagicText + FeatureText, true,
            new CryptoPP::StreamTransformationFilter( Encryptor,
                new CryptoPP::Base32Encoder(
                    new CryptoPP::StringSink( EncodedText ),
                true, 4, "-") // Base32Encoder
            ) // StreamTransformationFilter
        ); // StringSource

        // Add Appendage for Pretty Printing
        EncodedText += "JW";

        //////////////////////////////////////////
        //                Output                //
        //////////////////////////////////////////
        std::cout << EncodedText << std::endl;

        //////////////////////////////////////////
        //                  DMZ                 //
        //////////////////////////////////////////

        // Recovered Text Sink
        std::string RecoveredText = "";

        // Remove Appendage for Pretty Printing
        EncodedText = EncodedText.substr( 0, EncodedText.length() - 2 );

        CryptoPP::StringSource( EncodedText, true,
            new CryptoPP::Base32Decoder(
                new CryptoPP::StreamTransformationFilter( Decryptor,
                    new CryptoPP::StringSink( RecoveredText )
                ) // StreamTransformationFilter
            ) // Base32Decoder
        ); // StringSource

        // Salt
        unsigned int RecoveredSalt =
            *( (unsigned int*)(RecoveredText.substr( 0, 4 ).data() ) );
        // Step Over Salt
        assert( RecoveredText.length() >= 4 );
        RecoveredText = RecoveredText.substr( 4 );
        
        // Magic
        unsigned int RecoveredMagic =
            *( (unsigned int*)(RecoveredText.substr( 0, 4 ).data() ) );
        // Step Over Magic
        assert( RecoveredText.length() >= 4 );
        RecoveredText = RecoveredText.substr( 4 );

        //////////////////////////////////////////
        //            Key Tampering?            //
        //////////////////////////////////////////
        assert( FEATURE_MAGIC == RecoveredMagic );

        // Features
        unsigned int RecoveredFeatures =
            *( (unsigned int*)(RecoveredText.substr( 0, 4 ).data() ) );
        // Step over Features
        assert( RecoveredText.length() >= 4 );
        RecoveredText = RecoveredText.substr( 4 );

        //////////////////////////////////////////
        //                Output                //
        //////////////////////////////////////////
        PrintFeatures( RecoveredFeatures );


    } // for( ITERATIONS )
   
    return 0;
}

void EncodeFeatures( std::string& FeatureText, unsigned int features )
{
    assert( 4 == sizeof( unsigned int ) );
    
    char c = '\0';

    c = ( features >>  0 ) & 0xFF;
    FeatureText += c;

    c = ( features >>  8 ) & 0xFF;
    FeatureText += c;

    c = ( features >>  16 ) & 0xFF;
    FeatureText += c;

    c = ( features >>  24 ) & 0xFF;
    FeatureText += c;
}
void PrintPrologue( std::string algorithm, byte* key,
                    int keylen, byte* iv, int ivlen )
{
    std::string HexKey, HexIV;

    CryptoPP::HexEncoder KeyEncoder( NULL, true, 2 );
    KeyEncoder.Attach( new CryptoPP::StringSink( HexKey ) );
    KeyEncoder.PutMessageEnd( key, keylen );

    CryptoPP::HexEncoder IVEncoder( NULL, true, 2 );
    IVEncoder.Attach( new CryptoPP::StringSink( HexIV ) );
    IVEncoder.PutMessageEnd( iv, ivlen );
    
    std::cout << algorithm << std::endl;
    std::cout << "key[] = " << HexKey << std::endl;
    std::cout << " iv[] = " << HexIV << std::endl;
    std::cout << std::endl;
}

void PrintFeatures( unsigned int features )
{
    if( FEATURE_EVALUATION == ( features & FEATURE_EVALUATION ) )
    { std::cout << "Evaluation Edition" << std::endl; }
    
    if( FEATURE_USE_SQUARES == ( features & FEATURE_USE_SQUARES ) )
    { std::cout << "Operations are permitted on Squares" << std::endl; }
    
    if( FEATURE_USE_CIRCLES == ( features & FEATURE_USE_CIRCLES ) )
    { std::cout << "Operations are permitted on Circles" << std::endl; }
    
    if( FEATURE_USE_WIDGETS == ( features & FEATURE_USE_WIDGETS ) )
    { std::cout << "Operations are permitted on Widgets" << std::endl; }
    
    if( FEATURE_USE_ELLIPSES == ( features & FEATURE_USE_ELLIPSES ) )
    { std::cout << "Operations are permitted on Ellipses" << std::endl; }
    
    if( FEATURE_USE_POLYGONS == ( features & FEATURE_USE_POLYGONS ) )
    { std::cout << "Operations are permitted on Polygons" << std::endl; }
    
    if( FEATURE_USE_TRIANGLES == ( features & FEATURE_USE_TRIANGLES ) )
    { std::cout << "Operations are permitted on Triangles" << std::endl; }
    
    if( FEATURE_USE_PENTAGONS == ( features & FEATURE_USE_PENTAGONS ) )
    { std::cout << "Operations are permitted on Pentagons" << std::endl; }
    
    std::cout << std::endl;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems / Hardware Administrator
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions