Update documentation

Whitespace check-in
pull/548/head
Jeffrey Walton 2017-11-20 08:33:33 -05:00
parent 93fb412215
commit 4b3560baef
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
3 changed files with 268 additions and 217 deletions

View File

@ -14,9 +14,9 @@ Currently the library contains the following algorithms:
AES and AES candidates AES (Rijndael), RC6, MARS, Twofish, Serpent,
CAST-256
ARIA, IDEA, Triple-DES (DES-EDE2 and DES-EDE3),
other block ciphers Camellia, SEED, Kalyna, RC5, Blowfish, TEA, XTEA,
Threefish, Skipjack, SHACAL-2
ARIA, IDEA, Blowfish, Triple-DES (DES-EDE2 and
other block ciphers DES-EDE3), Camellia, SEED, Kalyna, RC5, SPECK-64,
SPECK-128, Threefish, Skipjack, SHACAL-2, TEA, XTEA
block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS),
CFB, OFB, counter mode (CTR)

392
speck.cpp
View File

@ -18,108 +18,138 @@ using CryptoPP::rotrFixed;
using CryptoPP::rotlVariable;
using CryptoPP::rotrVariable;
//! \brief Forward round transformation
//! \tparam W word type
template <class W>
inline void TF83(W& x, W& y, const W& k)
{
x = rotrFixed(x, 8);
x += y; x ^= k;
y = rotlFixed(y, 3);
y ^= x;
x = rotrFixed(x, 8);
x += y; x ^= k;
y = rotlFixed(y, 3);
y ^= x;
}
//! \brief Reverse round transformation
//! \tparam W word type
template <class W>
inline void TR83(W& x, W& y, const W& k)
{
y^=x;
y=rotrFixed(y,3);
x^=k;
x-=y;
x=rotlFixed(x,8);
y^=x;
y=rotrFixed(y,3);
x^=k; x-=y;
x=rotlFixed(x,8);
}
// W is word type
// R is number of rounds
// p = plain text, k = key, c = cipher text
//! \brief Forward transformation
//! \tparam W word type
//! \tparam R number of rounds
//! \param c output array
//! \param p input array
//! \param k subkey array
template <class W, unsigned int R>
inline void SPECK_Encrypt(W c[2], const W p[2], const W k[R])
{
c[0]=p[0]; c[1]=p[1];
c[0]=p[0]; c[1]=p[1];
// Don't unroll this loop. Things slow down.
for(W i=0; static_cast<int>(i)<R; ++i)
TF83(c[0], c[1], k[i]);
// Don't unroll this loop. Things slow down.
for(W i=0; static_cast<int>(i)<R; ++i)
TF83(c[0], c[1], k[i]);
}
//! \brief Reverse transformation
//! \tparam W word type
//! \tparam R number of rounds
//! \param p output array
//! \param c input array
//! \param k subkey array
template <class W, unsigned int R>
inline void SPECK_Decrypt(W p[2], const W c[2], const W k[R])
{
p[0]=c[0]; p[1]=c[1];
p[0]=c[0]; p[1]=c[1];
// Don't unroll this loop. Things slow down.
for(W i=R-1; static_cast<int>(i)>=0; --i)
TR83(p[0], p[1], k[i]);
// Don't unroll this loop. Things slow down.
for(W i=R-1; static_cast<int>(i)>=0; --i)
TR83(p[0], p[1], k[i]);
}
//! \brief Subkey generation function
//! \details Used when the user key consists of 2 words
//! \tparam W word type
//! \tparam R number of rounds
//! \param key empty subkey array
//! \param k user key array
template <class W, unsigned int R>
inline void SPECK_RoundKeys_2W(W key[R], const W k[2])
{
CRYPTOPP_ASSERT(R==32);
W i=0, B=k[1], A=k[0];
CRYPTOPP_ASSERT(R==32);
W i=0, B=k[1], A=k[0];
while(i<R-1)
{
key[i]=A; TF83(B, A, i);
i++;
}
key[R-1]=A;
while(i<R-1)
{
key[i]=A; TF83(B, A, i);
i++;
}
key[R-1]=A;
}
//! \brief Subkey generation function
//! \details Used when the user key consists of 3 words
//! \tparam W word type
//! \tparam R number of rounds
//! \param key empty subkey array
//! \param k user key array
template <class W, unsigned int R>
inline void SPECK_RoundKeys_3W(W key[R], const W k[3])
{
CRYPTOPP_ASSERT(R==33 || R==26);
W i=0, C=k[2], B=k[1], A=k[0];
CRYPTOPP_ASSERT(R==33 || R==26);
W i=0, C=k[2], B=k[1], A=k[0];
unsigned int blocks = R/2;
while(blocks--)
{
key[i+0]=A; TF83(B, A, i+0);
key[i+1]=A; TF83(C, A, i+1);
i+=2;
}
unsigned int blocks = R/2;
while(blocks--)
{
key[i+0]=A; TF83(B, A, i+0);
key[i+1]=A; TF83(C, A, i+1);
i+=2;
}
// The constexpr residue should allow the optimizer to remove unneeded statements
if(R%2 == 1)
{
key[R-1]=A;
}
// The constexpr residue should allow the optimizer to remove unneeded statements
if(R%2 == 1)
{
key[R-1]=A;
}
}
//! \brief Subkey generation function
//! \details Used when the user key consists of 4 words
//! \tparam W word type
//! \tparam R number of rounds
//! \param key empty subkey array
//! \param k user key array
template <class W, unsigned int R>
inline void SPECK_RoundKeys_4W(W key[R], const W k[4])
{
CRYPTOPP_ASSERT(R==34 || R==27);
W i=0, D=k[3], C=k[2], B=k[1], A=k[0];
CRYPTOPP_ASSERT(R==34 || R==27);
W i=0, D=k[3], C=k[2], B=k[1], A=k[0];
unsigned int blocks = R/3;
while(blocks--)
{
key[i+0]=A; TF83(B, A, i+0);
key[i+1]=A; TF83(C, A, i+1);
key[i+2]=A; TF83(D, A, i+2);
i+=3;
}
unsigned int blocks = R/3;
while(blocks--)
{
key[i+0]=A; TF83(B, A, i+0);
key[i+1]=A; TF83(C, A, i+1);
key[i+2]=A; TF83(D, A, i+2);
i+=3;
}
// The constexpr residue should allow the optimizer to remove unneeded statements
if(R%3 == 1)
{
key[R-1]=A;
}
else if(R%3 == 2)
{
key[R-2]=A; TF83(B, A, W(R-2));
key[R-1]=A;
}
// The constexpr residue should allow the optimizer to remove unneeded statements
if(R%3 == 1)
{
key[R-1]=A;
}
else if(R%3 == 2)
{
key[R-2]=A; TF83(B, A, W(R-2));
key[R-1]=A;
}
}
ANONYMOUS_NAMESPACE_END
@ -128,169 +158,169 @@ NAMESPACE_BEGIN(CryptoPP)
void SPECK64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
{
CRYPTOPP_ASSERT(keyLength == 12 || keyLength == 16);
CRYPTOPP_ASSERT(keyLength == 12 || keyLength == 16);
// Building the key schedule table requires {3,4} words workspace.
// Encrypting and decrypting requires 4 words workspace.
m_kwords = keyLength/sizeof(word32);
m_wspace.New(STDMAX(m_kwords,4U));
// Building the key schedule table requires {3,4} words workspace.
// Encrypting and decrypting requires 4 words workspace.
m_kwords = keyLength/sizeof(word32);
m_wspace.New(STDMAX(m_kwords,4U));
// Avoid GetUserKey. SPECK does unusual things with key string and word ordering
// {A,B} -> {B,A}, {A,B,C} -> {C,B,A}, etc.
typedef GetBlock<word32, BigEndian, false> InBlock;
InBlock iblk(userKey);
// Avoid GetUserKey. SPECK does unusual things with key string and word ordering
// {A,B} -> {B,A}, {A,B,C} -> {C,B,A}, etc.
typedef GetBlock<word32, BigEndian, false> InBlock;
InBlock iblk(userKey);
switch (m_kwords)
{
case 3:
m_rkey.New(26);
iblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SPECK_RoundKeys_3W<word32, 26>(m_rkey, m_wspace);
break;
case 4:
m_rkey.New(27);
iblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SPECK_RoundKeys_4W<word32, 27>(m_rkey, m_wspace);
break;
default:
CRYPTOPP_ASSERT(0);;
}
switch (m_kwords)
{
case 3:
m_rkey.New(26);
iblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SPECK_RoundKeys_3W<word32, 26>(m_rkey, m_wspace);
break;
case 4:
m_rkey.New(27);
iblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SPECK_RoundKeys_4W<word32, 27>(m_rkey, m_wspace);
break;
default:
CRYPTOPP_ASSERT(0);;
}
}
void SPECK64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Reverse bytes on LittleEndian; align pointer on BigEndian
typedef GetBlock<word32, BigEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
typedef GetBlock<word32, BigEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
switch (m_kwords)
{
case 3:
SPECK_Encrypt<word32, 26>(m_wspace+2, m_wspace+0, m_rkey);
break;
case 4:
SPECK_Encrypt<word32, 27>(m_wspace+2, m_wspace+0, m_rkey);
break;
default:
CRYPTOPP_ASSERT(0);;
}
switch (m_kwords)
{
case 3:
SPECK_Encrypt<word32, 26>(m_wspace+2, m_wspace+0, m_rkey);
break;
case 4:
SPECK_Encrypt<word32, 27>(m_wspace+2, m_wspace+0, m_rkey);
break;
default:
CRYPTOPP_ASSERT(0);;
}
// Reverse bytes on LittleEndian; align pointer on BigEndian
// Reverse bytes on LittleEndian; align pointer on BigEndian
typedef PutBlock<word32, BigEndian, false> OutBlock;
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
}
void SPECK64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Reverse bytes on LittleEndian; align pointer on BigEndian
typedef GetBlock<word32, BigEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
typedef GetBlock<word32, BigEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
switch (m_kwords)
{
case 3:
SPECK_Decrypt<word32, 26>(m_wspace+2, m_wspace+0, m_rkey);
break;
case 4:
SPECK_Decrypt<word32, 27>(m_wspace+2, m_wspace+0, m_rkey);
break;
default:
CRYPTOPP_ASSERT(0);;
}
switch (m_kwords)
{
case 3:
SPECK_Decrypt<word32, 26>(m_wspace+2, m_wspace+0, m_rkey);
break;
case 4:
SPECK_Decrypt<word32, 27>(m_wspace+2, m_wspace+0, m_rkey);
break;
default:
CRYPTOPP_ASSERT(0);;
}
// Reverse bytes on LittleEndian; align pointer on BigEndian
// Reverse bytes on LittleEndian; align pointer on BigEndian
typedef PutBlock<word32, BigEndian, false> OutBlock;
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
}
///////////////////////////////////////////////////////////
void SPECK128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
{
CRYPTOPP_ASSERT(keyLength == 16 || keyLength == 24 || keyLength == 32);
CRYPTOPP_ASSERT(keyLength == 16 || keyLength == 24 || keyLength == 32);
// Building the key schedule table requires {2,3,4} words workspace.
// Encrypting and decrypting requires 4 words workspace.
m_kwords = keyLength/sizeof(word64);
m_wspace.New(STDMAX(m_kwords,4U));
// Building the key schedule table requires {2,3,4} words workspace.
// Encrypting and decrypting requires 4 words workspace.
m_kwords = keyLength/sizeof(word64);
m_wspace.New(STDMAX(m_kwords,4U));
// Avoid GetUserKey. SPECK does unusual things with key string and word ordering
// {A,B} -> {B,A}, {A,B,C} -> {C,B,A}, etc.
typedef GetBlock<word64, BigEndian, false> InBlock;
InBlock iblk(userKey);
// Avoid GetUserKey. SPECK does unusual things with key string and word ordering
// {A,B} -> {B,A}, {A,B,C} -> {C,B,A}, etc.
typedef GetBlock<word64, BigEndian, false> InBlock;
InBlock iblk(userKey);
switch (m_kwords)
{
case 2:
m_rkey.New(32);
iblk(m_wspace[1])(m_wspace[0]);
SPECK_RoundKeys_2W<word64, 32>(m_rkey, m_wspace);
break;
case 3:
m_rkey.New(33);
iblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SPECK_RoundKeys_3W<word64, 33>(m_rkey, m_wspace);
break;
case 4:
m_rkey.New(34);
iblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SPECK_RoundKeys_4W<word64, 34>(m_rkey, m_wspace);
break;
default:
CRYPTOPP_ASSERT(0);;
}
switch (m_kwords)
{
case 2:
m_rkey.New(32);
iblk(m_wspace[1])(m_wspace[0]);
SPECK_RoundKeys_2W<word64, 32>(m_rkey, m_wspace);
break;
case 3:
m_rkey.New(33);
iblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SPECK_RoundKeys_3W<word64, 33>(m_rkey, m_wspace);
break;
case 4:
m_rkey.New(34);
iblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
SPECK_RoundKeys_4W<word64, 34>(m_rkey, m_wspace);
break;
default:
CRYPTOPP_ASSERT(0);;
}
}
void SPECK128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Reverse bytes on LittleEndian; align pointer on BigEndian
typedef GetBlock<word64, BigEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
typedef GetBlock<word64, BigEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
switch (m_kwords)
{
case 2:
SPECK_Encrypt<word64, 32>(m_wspace+2, m_wspace+0, m_rkey);
break;
case 3:
SPECK_Encrypt<word64, 33>(m_wspace+2, m_wspace+0, m_rkey);
break;
case 4:
SPECK_Encrypt<word64, 34>(m_wspace+2, m_wspace+0, m_rkey);
break;
default:
CRYPTOPP_ASSERT(0);;
}
switch (m_kwords)
{
case 2:
SPECK_Encrypt<word64, 32>(m_wspace+2, m_wspace+0, m_rkey);
break;
case 3:
SPECK_Encrypt<word64, 33>(m_wspace+2, m_wspace+0, m_rkey);
break;
case 4:
SPECK_Encrypt<word64, 34>(m_wspace+2, m_wspace+0, m_rkey);
break;
default:
CRYPTOPP_ASSERT(0);;
}
// Reverse bytes on LittleEndian; align pointer on BigEndian
// Reverse bytes on LittleEndian; align pointer on BigEndian
typedef PutBlock<word64, BigEndian, false> OutBlock;
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
}
void SPECK128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
{
// Reverse bytes on LittleEndian; align pointer on BigEndian
typedef GetBlock<word64, BigEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
typedef GetBlock<word64, BigEndian, false> InBlock;
InBlock iblk(inBlock); iblk(m_wspace[0])(m_wspace[1]);
switch (m_kwords)
{
case 2:
SPECK_Decrypt<word64, 32>(m_wspace+2, m_wspace+0, m_rkey);
break;
case 3:
SPECK_Decrypt<word64, 33>(m_wspace+2, m_wspace+0, m_rkey);
break;
case 4:
SPECK_Decrypt<word64, 34>(m_wspace+2, m_wspace+0, m_rkey);
break;
default:
CRYPTOPP_ASSERT(0);;
}
switch (m_kwords)
{
case 2:
SPECK_Decrypt<word64, 32>(m_wspace+2, m_wspace+0, m_rkey);
break;
case 3:
SPECK_Decrypt<word64, 33>(m_wspace+2, m_wspace+0, m_rkey);
break;
case 4:
SPECK_Decrypt<word64, 34>(m_wspace+2, m_wspace+0, m_rkey);
break;
default:
CRYPTOPP_ASSERT(0);;
}
// Reverse bytes on LittleEndian; align pointer on BigEndian
// Reverse bytes on LittleEndian; align pointer on BigEndian
typedef PutBlock<word64, BigEndian, false> OutBlock;
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[2])(m_wspace[3]);
}
NAMESPACE_END

87
speck.h
View File

@ -21,6 +21,9 @@ NAMESPACE_BEGIN(CryptoPP)
//! \class SPECK_Info
//! \brief SPECK block cipher information
//! \tparam BS block size of the cipher, in bytes
//! \tparam D default key length, in bytes
//! \tparam N minimum key length, in bytes
//! \tparam M maximum key length, in bytes
//! \since Crypto++ 6.0
template <unsigned int BS, unsigned int D, unsigned int N, unsigned int M>
struct SPECK_Info : public FixedBlockSize<BS>, VariableKeyLength<D, N, M>
@ -35,23 +38,25 @@ struct SPECK_Info : public FixedBlockSize<BS>, VariableKeyLength<D, N, M>
//! \class SPECK_Base
//! \brief SPECK block cipher base class
//! \tparam BS block size of the cipher, in bytes
//! \details User code should use SPECK128, SPECK512, SPECK1024
//! \sa SPECK32, SPECK48, SPECK64, SPECK96, SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
//! \details User code should use SPECK64 or SPECK128
//! \sa SPECK64, SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
//! \since Crypto++ 6.0
template <class W>
struct SPECK_Base
{
virtual ~SPECK_Base() {}
typedef SecBlock<W, AllocatorWithCleanup<W, true> > AlignedSecBlock;
mutable AlignedSecBlock m_wspace; // workspace
AlignedSecBlock m_rkey; // round keys
unsigned int m_kwords; // number of key words
unsigned int m_kwords; // number of key words
};
//! \class SPECK64
//! \brief SPECK 64-bit block cipher
//! \details SPECK64 provides 64-bit block size. The valid key sizes are 98-bit and 128-bit.
//! \note Crypto++ provides a byte oriented implementation
//! \sa SPECK32, SPECK64, and SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
//! \sa SPECK64, SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
//! \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE SPECK64 : public SPECK_Info<8, 12, 12, 16>, public BlockCipherDocumentation
{
@ -61,26 +66,34 @@ public:
//! \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Base : protected SPECK_Base<word32>, public BlockCipherImpl<SPECK_Info<8, 12, 12, 16> >
{
public:
std::string AlgorithmName() const {
return StaticAlgorithmName() + "(" + IntToString(m_kwords*sizeof(word32)*8) + ")";
}
public:
std::string AlgorithmName() const {
return StaticAlgorithmName() + "(" + IntToString(m_kwords*sizeof(word32)*8) + ")";
}
protected:
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
};
class CRYPTOPP_NO_VTABLE Enc : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
//! \brief Provides implementation for encryption transformation
//! \details Enc provides implementation for encryption transformation. All key
//! sizes are supported.
//! \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Enc : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
class CRYPTOPP_NO_VTABLE Dec : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
//! \brief Provides implementation for encryption transformation
//! \details Dec provides implementation for decryption transformation. All key
//! sizes are supported.
//! \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Dec : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
@ -90,7 +103,7 @@ public:
//! \brief SPECK 128-bit block cipher
//! \details SPECK128 provides 128-bit block size. The valid key sizes are 128-bit, 192-bit and 256-bit.
//! \note Crypto++ provides a byte oriented implementation
//! \sa SPECK32, SPECK64, and SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
//! \sa SPECK64, SPECK128, <a href="http://www.cryptopp.com/wiki/SPECK">SPECK</a>
//! \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE SPECK128 : public SPECK_Info<16, 16, 16, 32>, public BlockCipherDocumentation
{
@ -100,26 +113,34 @@ public:
//! \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Base : protected SPECK_Base<word64>, public BlockCipherImpl<SPECK_Info<16, 16, 16, 32> >
{
public:
std::string AlgorithmName() const {
return StaticAlgorithmName() + "(" + IntToString(sizeof(word64)*8) + ")";
}
public:
std::string AlgorithmName() const {
return StaticAlgorithmName() + "(" + IntToString(sizeof(word64)*8) + ")";
}
protected:
void UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params);
};
class CRYPTOPP_NO_VTABLE Enc : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
//! \brief Provides implementation for encryption transformation
//! \details Enc provides implementation for encryption transformation. All key
//! sizes are supported.
//! \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Enc : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
class CRYPTOPP_NO_VTABLE Dec : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
//! \brief Provides implementation for encryption transformation
//! \details Dec provides implementation for decryption transformation. All key
//! sizes are supported.
//! \since Crypto++ 6.0
class CRYPTOPP_NO_VTABLE Dec : public Base
{
protected:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
};
typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;