ida.h 5.16 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
// ida.h - written and placed in the public domain by Wei Dai

//! \file ida.h
//! \brief Classes for Information Dispersal Algorithm (IDA)

#ifndef CRYPTOPP_IDA_H
#define CRYPTOPP_IDA_H

#include "cryptlib.h"
#include "mqueue.h"
#include "filters.h"
#include "channels.h"
#include "secblock.h"
#include "stdcpp.h"
#include "misc.h"

NAMESPACE_BEGIN(CryptoPP)

/// base class for secret sharing and information dispersal
class RawIDA : public AutoSignaling<Unflushable<Multichannel<Filter> > >
{
public:
	RawIDA(BufferedTransformation *attachment=NULL)
		: m_threshold (0), m_channelsReady(0), m_channelsFinished(0)
			{Detach(attachment);}

	unsigned int GetThreshold() const {return m_threshold;}
	void AddOutputChannel(word32 channelId);
	void ChannelData(word32 channelId, const byte *inString, size_t length, bool messageEnd);
	lword InputBuffered(word32 channelId) const;

	void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);
	size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
	{
		if (!blocking)
			throw BlockingInputOnly("RawIDA");
		ChannelData(StringToWord<word32>(channel), begin, length, messageEnd != 0);
		return 0;
	}

protected:
	virtual void FlushOutputQueues();
	virtual void OutputMessageEnds();

	unsigned int InsertInputChannel(word32 channelId);
	unsigned int LookupInputChannel(word32 channelId) const;
	void ComputeV(unsigned int);
	void PrepareInterpolation();
	void ProcessInputQueues();

	typedef std::map<word32, unsigned int> InputChannelMap;
	InputChannelMap m_inputChannelMap;
	InputChannelMap::iterator m_lastMapPosition;
	std::vector<MessageQueue> m_inputQueues;
	std::vector<word32> m_inputChannelIds, m_outputChannelIds, m_outputToInput;
	std::vector<std::string> m_outputChannelIdStrings;
	std::vector<ByteQueue> m_outputQueues;
	int m_threshold;
	unsigned int m_channelsReady, m_channelsFinished;
	std::vector<SecBlock<word32> > m_v;
	SecBlock<word32> m_u, m_w, m_y;
};

/// a variant of Shamir's Secret Sharing Algorithm
class SecretSharing : public CustomFlushPropagation<Filter>
{
public:
	SecretSharing(RandomNumberGenerator &rng, int threshold, int nShares, BufferedTransformation *attachment=NULL, bool addPadding=true)
		: m_rng(rng), m_ida(new OutputProxy(*this, true))
	{
		Detach(attachment);
		IsolatedInitialize(MakeParameters("RecoveryThreshold", threshold)("NumberOfShares", nShares)("AddPadding", addPadding));
	}

	void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);
	size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
	bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) {return m_ida.Flush(hardFlush, propagation, blocking);}

protected:
	RandomNumberGenerator &m_rng;
	RawIDA m_ida;
	bool m_pad;
};

/// a variant of Shamir's Secret Sharing Algorithm
class SecretRecovery : public RawIDA
{
public:
	SecretRecovery(int threshold, BufferedTransformation *attachment=NULL, bool removePadding=true)
		: RawIDA(attachment)
		{IsolatedInitialize(MakeParameters("RecoveryThreshold", threshold)("RemovePadding", removePadding));}

	void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);

protected:
	void FlushOutputQueues();
	void OutputMessageEnds();

	bool m_pad;
};

/// a variant of Rabin's Information Dispersal Algorithm
class InformationDispersal : public CustomFlushPropagation<Filter>
{
public:
	InformationDispersal(int threshold, int nShares, BufferedTransformation *attachment=NULL, bool addPadding=true)
		: m_ida(new OutputProxy(*this, true)), m_pad(false), m_nextChannel(0)
	{
		Detach(attachment);
		IsolatedInitialize(MakeParameters("RecoveryThreshold", threshold)("NumberOfShares", nShares)("AddPadding", addPadding));
	}

	void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);
	size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
	bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) {return m_ida.Flush(hardFlush, propagation, blocking);}

protected:
	RawIDA m_ida;
	bool m_pad;
	unsigned int m_nextChannel;
};

/// a variant of Rabin's Information Dispersal Algorithm
class InformationRecovery : public RawIDA
{
public:
	InformationRecovery(int threshold, BufferedTransformation *attachment=NULL, bool removePadding=true)
		: RawIDA(attachment), m_pad(false)
		{IsolatedInitialize(MakeParameters("RecoveryThreshold", threshold)("RemovePadding", removePadding));}

	void IsolatedInitialize(const NameValuePairs &parameters=g_nullNameValuePairs);

protected:
	void FlushOutputQueues();
	void OutputMessageEnds();

	bool m_pad;
	ByteQueue m_queue;
};

class PaddingRemover : public Unflushable<Filter>
{
public:
	PaddingRemover(BufferedTransformation *attachment=NULL)
		: m_possiblePadding(false), m_zeroCount(0) {Detach(attachment);}

	void IsolatedInitialize(const NameValuePairs &parameters)
		{CRYPTOPP_UNUSED(parameters); m_possiblePadding = false;}
	size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);

	// GetPossiblePadding() == false at the end of a message indicates incorrect padding
	bool GetPossiblePadding() const {return m_possiblePadding;}

private:
	bool m_possiblePadding;
	lword m_zeroCount;
};

NAMESPACE_END

#endif