算法描述:ftp://ebible.org/pub/public/sapphire.pdf

VS2010新建控制台空项目,加入下面的代码:

CSapphire.h:

#ifndef __CSAPPHIRE_H__
#define __CSAPPHIRE_H__

class CSapphire {
public:
	CSapphire(unsigned char *key = 0,  unsigned char keysize = 0);		// Calls initialize if a real key is provided.  If none is provided, call initialize before encrypt or decrypt.

	~CSapphire();							// Destroy cipher state information.

	void initialize(unsigned char *key,	unsigned char keysize);		// User key is used to set up state information.

	void hash_init(void);						// Set up default hash.

	unsigned char encrypt(unsigned char b = 0);	// Encrypt byte or get a random byte.

	unsigned char decrypt(unsigned char b);		// Decrypt byte.

	void hash_final(unsigned char *hash, unsigned char hashlength = 20);		// Copy hash value to hash Hash length (16-32)

	void burn(void);						// Destroy cipher state information.

private:
	unsigned char cards[256];					// A permutation of 0-255.
	unsigned char rotor,						// Index that rotates smoothly
			ratchet,							// Index that moves erratically
			avalanche,							// Index heavily data dependent
			last_plain,								// Last plain text byte
			last_cipher;							// Last cipher text byte

	unsigned char keyrand(int limit, unsigned char *user_key, unsigned char keysize, unsigned char *rsum, unsigned *keypos);
};


#endif



CSapphire.cpp:


#include "CSapphire.h"
#include <string.h>

unsigned char CSapphire::keyrand(int limit, unsigned char *user_key, unsigned char keysize, unsigned char *rsum, unsigned *keypos) {
	unsigned u;				// Value from 0 to limit to return.
	unsigned retry_limiter = 0;	// No infinite loops allowed.
	unsigned mask = 1;				// Select just enough bits.

	while (mask < limit)		// the desired range.
		mask = (mask << 1) + 1;

	do {
		*rsum = cards[*rsum] + user_key[(*keypos)++];
		if (*keypos >= keysize) {
			*keypos = 0;		// Recycle the user key.
			*rsum += keysize;	// key "aaaa" != key "aaaaaaaa"
		}
		u = mask & *rsum;
		if (++retry_limiter > 11)
			u %= limit;		// Prevent very rare long loops.
	} while (u > limit);

	return u;
}

void CSapphire::initialize(unsigned char *key, unsigned char keysize) {
	// Key size may be up to 256 bytes.
	// Pass phrases may be used directly, with longer length
	// compensating for the low entropy expected in such keys.
	// Alternatively, shorter keys hashed from a pass phrase or
	// generated randomly may be used. For random keys, lengths
	// of from 4 to 16 bytes are recommended, depending on how
	// secure you want this to be.

	int i;
	unsigned char toswap, swaptemp, rsum;
	unsigned keypos;

	// If we have been given no key, assume the default hash setup.
	if (keysize < 1) {
		hash_init();
		return;
	}

	// Start with cards all in order, one of each.
	for (i = 0; i < 256; i++)
		cards[i] = i;

	// Swap the card at each position with some other card.
	toswap = 0;
	keypos = 0;
	rsum = 0; // Start with first byte of user key.
	for (i = 255; i >= 0; i--) {
		toswap = keyrand(i, key, keysize, &rsum, &keypos);
		swaptemp = cards[i];
		cards[i] = cards[toswap];
		cards[toswap] = swaptemp;
	}

	// Initialize the indices and data dependencies.
	// Indices are set to different values instead of all 0
	// to reduce what is known about the state of the cards
	// when the first byte is emitted.
	rotor = cards[1];
	ratchet = cards[3];
	avalanche = cards[5];
	last_plain = cards[7];
	last_cipher = cards[rsum];

	toswap = swaptemp = rsum = 0;
	keypos = 0;
}

void CSapphire::hash_init(void) {
	// This function is used to initialize non-keyed hash computation.
	// Initialize the indices and data dependencies.
	rotor = 1;
	ratchet = 3;
	avalanche = 5;
	last_plain = 7;
	last_cipher = 11;

	// Start with cards all in inverse order.
	for (int i = 0, j = 255; i < 256; i++, j--)
		cards[i] = (unsigned char) j;
}

CSapphire::CSapphire(unsigned char *key, unsigned char keysize) {
	if (key && keysize)
		initialize(key, keysize);
}

void CSapphire::burn(void) {
	// Destroy the key and state information in RAM.
	memset(cards, 0, 256);
	rotor = ratchet = avalanche = last_plain = last_cipher = 0;
}

CSapphire::~CSapphire() {
	burn();
}

unsigned char CSapphire::encrypt(unsigned char b) {
	// Picture a single enigma rotor with 256 positions, rewired
	// on the fly by card-shuffling.

	// This cipher is a variant of one invented and written
	// by Michael Paul Johnson in November, 1993.

	unsigned char swaptemp;

	// Shuffle the deck a little more.
	ratchet += cards[rotor++];
	swaptemp = cards[last_cipher];
	cards[last_cipher] = cards[ratchet];
	cards[ratchet] = cards[last_plain];
	cards[last_plain] = cards[rotor];
	cards[rotor] = swaptemp;
	avalanche += cards[swaptemp];

	// Output one byte from the state in such a way as to make it
	// very hard to figure out which one you are looking at.
	last_cipher = b ^ cards[(cards[ratchet] + cards[rotor]) & 0xFF] ^ cards[cards[(cards[last_plain] + cards[last_cipher] + cards[avalanche]) & 0xFF]];
	last_plain = b;
	return last_cipher;
}

unsigned char CSapphire::decrypt(unsigned char b) {
	unsigned char swaptemp;

	// Shuffle the deck a little more.
	ratchet += cards[rotor++];
	swaptemp = cards[last_cipher];
	cards[last_cipher] = cards[ratchet];
	cards[ratchet] = cards[last_plain];
	cards[last_plain] = cards[rotor];
	cards[rotor] = swaptemp;
	avalanche += cards[swaptemp];

	// Output one byte from the state in such a way as to make it
	// very hard to figure out which one you are looking at.
	last_plain = b ^ cards[(cards[ratchet] + cards[rotor]) & 0xFF] ^ cards[cards[(cards[last_plain] + cards[last_cipher] + cards[avalanche]) & 0xFF]];
	last_cipher = b;
	return last_plain;
}

void CSapphire::hash_final(unsigned char *hash, unsigned char hashlength) {
	int i;
	for (i = 255; i >= 0; i--)
		encrypt((unsigned char) i);
	for (i = 0; i < hashlength; i++)
		hash[i] = encrypt(0);
}



测试代码main.cpp:

#include "CSapphire.h"
#include <stdio.h>
#include <string.h>

int main()
{
	char *pKey = "key";
	char *pPlaintext = "abcdefg";
	CSapphire sapphire;
	char ciphertext[200]={0};
	char plaintext[200]={0};
	printf("plaintext = %s\n", pPlaintext);
	sapphire.initialize((unsigned char*)pKey, strlen(pKey));
	for (char *p=pPlaintext;*p;p++) {
		char ch = sapphire.encrypt(*p);
		strncat(ciphertext, &ch, sizeof(ch));
	}
	printf("after encrypt ciphertext = %s\n", ciphertext);
	sapphire.burn();
	sapphire.initialize((unsigned char*)pKey, strlen(pKey));
	for (char *p=ciphertext;*p;p++) {
		char ch = sapphire.decrypt(*p);
		strncat(plaintext, &ch, sizeof(ch));
	}
	printf("after decrypt plaintext = %s\n", plaintext);
	sapphire.burn();
	return 0;
}