mce_qcmdpc: QC-MDPC McEliece

This commit is contained in:
Mirek Kratochvil 2015-11-07 19:35:04 +01:00
parent 878d326859
commit 17f77e16a4
6 changed files with 532 additions and 40 deletions

View file

@ -35,6 +35,14 @@ void fill_algorithm_suite (algorithm_suite&s)
do_alg (algo_mceqd128xs);
do_alg (algo_mceqd192xs);
do_alg (algo_mceqd256xs);
do_alg (algo_mceqcmdpc128);
do_alg (algo_mceqcmdpc256);
do_alg (algo_mceqcmdpc128cha);
do_alg (algo_mceqcmdpc256cha);
do_alg (algo_mceqcmdpc128xs);
do_alg (algo_mceqcmdpc256xs);
do_alg (algo_fmtseq128);
do_alg (algo_fmtseq192);
do_alg (algo_fmtseq256);
@ -52,6 +60,14 @@ void fill_algorithm_suite (algorithm_suite&s)
do_alg (algo_mceqd128cubexs);
do_alg (algo_mceqd192cubexs);
do_alg (algo_mceqd256cubexs);
do_alg (algo_mceqcmdpc128cube);
do_alg (algo_mceqcmdpc256cube);
do_alg (algo_mceqcmdpc128cubecha);
do_alg (algo_mceqcmdpc256cubecha);
do_alg (algo_mceqcmdpc128cubexs);
do_alg (algo_mceqcmdpc256cubexs);
do_alg (algo_fmtseq128cube);
do_alg (algo_fmtseq192cube);
do_alg (algo_fmtseq256cube);

View file

@ -19,6 +19,18 @@
#include "algos_enc.h"
#include "mce_qd.h"
#include "mce_qcmdpc.h"
#include "arcfour.h"
#include "chacha.h"
#include "xsynd.h"
#if HAVE_CRYPTOPP==1
#include "sha_hash.h"
#include "rmd_hash.h"
#endif
#include "cube_hash.h"
typedef arcfour<byte, 8, 4096> arcfour_fo_cipher;
/*
* keygen
@ -38,6 +50,20 @@ static int mceqd_create_keypair (sencode**pub, sencode**priv, prng&rng)
return 0;
}
template<int bs, int bc, int wi, int t, int rounds, int delta>
static int mceqcmdpc_create_keypair (sencode**pub, sencode**priv, prng&rng)
{
mce_qcmdpc::pubkey Pub;
mce_qcmdpc::privkey Priv;
if (mce_qcmdpc::generate (Pub, Priv, rng, bs, bc, wi, t, rounds, delta))
return 1;
*pub = Pub.serialize();
*priv = Priv.serialize();
return 0;
}
/*
* Padding. Ha-ha.
*
@ -393,7 +419,80 @@ static int fo_decrypt (const bvector&cipher, bvector&plain,
}
/*
* Instances for actual keygen/encryption/descryption algorithms
* Instances for MCE-QCMDPC algorithms
*/
#define mceqcmdpc_create_keypair_func(name,bs,bc,wi,t,rnd,delta) \
int algo_mceqcmdpc##name::create_keypair (sencode**pub, sencode**priv, prng&rng) \
{ \
return mceqcmdpc_create_keypair<bs,bc,wi,t,rnd,delta> (pub, priv, rng); \
}
#if HAVE_CRYPTOPP==1
mceqcmdpc_create_keypair_func (128, 9857, 2, 71, 134, 60, 7)
mceqcmdpc_create_keypair_func (256, 32771, 2, 137, 264, 60, 7)
mceqcmdpc_create_keypair_func (128cha, 9857, 2, 71, 134, 60, 7)
mceqcmdpc_create_keypair_func (256cha, 32771, 2, 137, 264, 60, 7)
mceqcmdpc_create_keypair_func (128xs, 9857, 2, 71, 134, 60, 7)
mceqcmdpc_create_keypair_func (256xs, 32771, 2, 137, 264, 60, 7)
#endif //HAVE_CRYPTOPP==1
mceqcmdpc_create_keypair_func (128cube, 9857, 2, 71, 134, 60, 7)
mceqcmdpc_create_keypair_func (256cube, 32771, 2, 137, 264, 60, 7)
mceqcmdpc_create_keypair_func (128cubecha, 9857, 2, 71, 134, 60, 7)
mceqcmdpc_create_keypair_func (256cubecha, 32771, 2, 137, 264, 60, 7)
mceqcmdpc_create_keypair_func (128cubexs, 9857, 2, 71, 134, 60, 7)
mceqcmdpc_create_keypair_func (256cubexs, 32771, 2, 137, 264, 60, 7)
#define mceqcmdpc_create_encdec_func(name,bs,bc,errcount,hash_type,pad_hash_type,scipher,ranksize) \
int algo_mceqcmdpc##name::encrypt (const bvector&plain, bvector&cipher, \
sencode* pubkey, prng&rng) \
{ \
return fo_encrypt \
< mce_qcmdpc::pubkey, \
bs*(bc-1), bs*bc, errcount, \
hash_type, \
pad_hash_type, \
scipher, \
ranksize > \
(plain, cipher, pubkey, rng); \
} \
int algo_mceqcmdpc##name::decrypt (const bvector&cipher, bvector&plain, \
sencode* privkey) \
{ \
return fo_decrypt \
< mce_qcmdpc::privkey, \
bs*(bc-1), bs*bc, errcount, \
hash_type, \
pad_hash_type, \
scipher, \
ranksize > \
(cipher, plain, privkey); \
}
#if HAVE_CRYPTOPP==1
mceqcmdpc_create_encdec_func (128, 9857, 2, 134, sha256hash, rmd128hash, arcfour_fo_cipher, 1152)
mceqcmdpc_create_encdec_func (256, 32771, 2, 264, sha512hash, sha256hash, arcfour_fo_cipher, 2475)
mceqcmdpc_create_encdec_func (128cha, 9857, 2, 134, sha256hash, rmd128hash, chacha20, 1152)
mceqcmdpc_create_encdec_func (256cha, 32771, 2, 264, sha512hash, sha256hash, chacha20, 2475)
mceqcmdpc_create_encdec_func (128xs, 9857, 2, 134, sha256hash, rmd128hash, xsynd, 1152)
mceqcmdpc_create_encdec_func (256xs, 32771, 2, 264, sha512hash, sha256hash, xsynd, 2475)
#endif //HAVE_CRYPTOPP==1
mceqcmdpc_create_encdec_func (128cube, 9857, 2, 134, cube256hash, cube128hash, arcfour_fo_cipher, 1152)
mceqcmdpc_create_encdec_func (256cube, 32771, 2, 264, cube512hash, cube256hash, arcfour_fo_cipher, 2475)
mceqcmdpc_create_encdec_func (128cubecha, 9857, 2, 134, cube256hash, cube128hash, chacha20, 1152)
mceqcmdpc_create_encdec_func (256cubecha, 32771, 2, 264, cube512hash, cube256hash, chacha20, 2475)
mceqcmdpc_create_encdec_func (128cubexs, 9857, 2, 134, cube256hash, cube128hash, xsynd, 1152)
mceqcmdpc_create_encdec_func (256cubexs, 32771, 2, 264, cube512hash, cube256hash, xsynd, 2475)
/*
* Instances for MCE-QD algorithms
*/
#define mceqd_create_keypair_func(name,m,T,b,d) \
@ -426,12 +525,6 @@ mceqd_create_keypair_func (128cubexs, 16, 7, 32, 4)
mceqd_create_keypair_func (192cubexs, 16, 8, 27, 4)
mceqd_create_keypair_func (256cubexs, 16, 8, 32, 4)
#include "arcfour.h"
#include "chacha.h"
#include "xsynd.h"
typedef arcfour<byte, 8, 4096> arcfour_fo_cipher;
#define mceqd_create_encdec_func(name,plainsize,ciphersize,errcount, hash_type,pad_hash_type,scipher,ranksize) \
int algo_mceqd##name::encrypt (const bvector&plain, bvector&cipher, \
sencode* pubkey, prng&rng) \
@ -461,9 +554,6 @@ int algo_mceqd##name::decrypt (const bvector&cipher, bvector&plain, \
#if HAVE_CRYPTOPP==1
#include "sha_hash.h"
#include "rmd_hash.h"
mceqd_create_encdec_func (128, 2048, 4096, 128, sha256hash, rmd128hash, arcfour_fo_cipher, 816)
mceqd_create_encdec_func (192, 2816, 6912, 256, sha384hash, rmd128hash, arcfour_fo_cipher, 1574)
mceqd_create_encdec_func (256, 4096, 8192, 256, sha512hash, rmd128hash, arcfour_fo_cipher, 1638)
@ -476,8 +566,6 @@ mceqd_create_encdec_func (256xs, 4096, 8192, 256, sha512hash, rmd128hash, xsynd,
#endif //HAVE_CRYPTOPP==1
#include "cube_hash.h"
mceqd_create_encdec_func (128cube, 2048, 4096, 128, cube256hash, cube128hash, arcfour_fo_cipher, 816)
mceqd_create_encdec_func (192cube, 2816, 6912, 256, cube384hash, cube128hash, arcfour_fo_cipher, 1574)
mceqd_create_encdec_func (256cube, 4096, 8192, 256, cube512hash, cube128hash, arcfour_fo_cipher, 1638)

View file

@ -21,8 +21,8 @@
#include "algorithm.h"
#define mceqd_alg_class(name,alg_id) \
class algo_mceqd##name : public algorithm \
#define mce_alg_class(name,alg_id) \
class algo_mce##name : public algorithm \
{ \
public: \
bool provides_signatures() { \
@ -47,15 +47,22 @@ public: \
* SHA-based variants
*/
mceqd_alg_class (128, "MCEQD128FO-SHA256-ARCFOUR");
mceqd_alg_class (192, "MCEQD192FO-SHA384-ARCFOUR");
mceqd_alg_class (256, "MCEQD256FO-SHA512-ARCFOUR");
mceqd_alg_class (128cha, "MCEQD128FO-SHA256-CHACHA20");
mceqd_alg_class (192cha, "MCEQD192FO-SHA384-CHACHA20");
mceqd_alg_class (256cha, "MCEQD256FO-SHA512-CHACHA20");
mceqd_alg_class (128xs, "MCEQD128FO-SHA256-XSYND");
mceqd_alg_class (192xs, "MCEQD192FO-SHA384-XSYND");
mceqd_alg_class (256xs, "MCEQD256FO-SHA512-XSYND");
mce_alg_class (qd128, "MCEQD128FO-SHA256-ARCFOUR");
mce_alg_class (qd192, "MCEQD192FO-SHA384-ARCFOUR");
mce_alg_class (qd256, "MCEQD256FO-SHA512-ARCFOUR");
mce_alg_class (qd128cha, "MCEQD128FO-SHA256-CHACHA20");
mce_alg_class (qd192cha, "MCEQD192FO-SHA384-CHACHA20");
mce_alg_class (qd256cha, "MCEQD256FO-SHA512-CHACHA20");
mce_alg_class (qd128xs, "MCEQD128FO-SHA256-XSYND");
mce_alg_class (qd192xs, "MCEQD192FO-SHA384-XSYND");
mce_alg_class (qd256xs, "MCEQD256FO-SHA512-XSYND");
mce_alg_class (qcmdpc128, "MCEQCMDPC128FO-SHA256-ARCFOUR");
mce_alg_class (qcmdpc256, "MCEQCMDPC256FO-SHA512-ARCFOUR");
mce_alg_class (qcmdpc128cha, "MCEQCMDPC128FO-SHA256-CHACHA20");
mce_alg_class (qcmdpc256cha, "MCEQCMDPC256FO-SHA512-CHACHA20");
mce_alg_class (qcmdpc128xs, "MCEQCMDPC128FO-SHA256-XSYND");
mce_alg_class (qcmdpc256xs, "MCEQCMDPC256FO-SHA512-XSYND");
#endif //HAVE_CRYPTOPP==1
@ -63,15 +70,21 @@ mceqd_alg_class (256xs, "MCEQD256FO-SHA512-XSYND");
* Cubehash-based variants
*/
mceqd_alg_class (128cube, "MCEQD128FO-CUBE256-ARCFOUR");
mceqd_alg_class (192cube, "MCEQD192FO-CUBE384-ARCFOUR");
mceqd_alg_class (256cube, "MCEQD256FO-CUBE512-ARCFOUR");
mceqd_alg_class (128cubecha, "MCEQD128FO-CUBE256-CHACHA20");
mceqd_alg_class (192cubecha, "MCEQD192FO-CUBE384-CHACHA20");
mceqd_alg_class (256cubecha, "MCEQD256FO-CUBE512-CHACHA20");
mceqd_alg_class (128cubexs, "MCEQD128FO-CUBE256-XSYND");
mceqd_alg_class (192cubexs, "MCEQD192FO-CUBE384-XSYND");
mceqd_alg_class (256cubexs, "MCEQD256FO-CUBE512-XSYND");
mce_alg_class (qd128cube, "MCEQD128FO-CUBE256-ARCFOUR");
mce_alg_class (qd192cube, "MCEQD192FO-CUBE384-ARCFOUR");
mce_alg_class (qd256cube, "MCEQD256FO-CUBE512-ARCFOUR");
mce_alg_class (qd128cubecha, "MCEQD128FO-CUBE256-CHACHA20");
mce_alg_class (qd192cubecha, "MCEQD192FO-CUBE384-CHACHA20");
mce_alg_class (qd256cubecha, "MCEQD256FO-CUBE512-CHACHA20");
mce_alg_class (qd128cubexs, "MCEQD128FO-CUBE256-XSYND");
mce_alg_class (qd192cubexs, "MCEQD192FO-CUBE384-XSYND");
mce_alg_class (qd256cubexs, "MCEQD256FO-CUBE512-XSYND");
mce_alg_class (qcmdpc128cube, "MCEQCMDPC128FO-CUBE256-ARCFOUR");
mce_alg_class (qcmdpc256cube, "MCEQCMDPC256FO-CUBE512-ARCFOUR");
mce_alg_class (qcmdpc128cubecha, "MCEQCMDPC128FO-CUBE256-CHACHA20");
mce_alg_class (qcmdpc256cubecha, "MCEQCMDPC256FO-CUBE512-CHACHA20");
mce_alg_class (qcmdpc128cubexs, "MCEQCMDPC128FO-CUBE256-XSYND");
mce_alg_class (qcmdpc256cubexs, "MCEQCMDPC256FO-CUBE512-XSYND");
#endif

222
src/mce_qcmdpc.cpp Normal file
View file

@ -0,0 +1,222 @@
/*
* This file is part of Codecrypt.
*
* Codecrypt is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Codecrypt is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Codecrypt. If not, see <http://www.gnu.org/licenses/>.
*/
#include "mce_qcmdpc.h"
#include "gf2m.h"
#include "polynomial.h"
using namespace mce_qcmdpc;
int mce_qcmdpc::generate (pubkey&pub, privkey&priv, prng&rng,
uint block_size, uint block_count, uint wi,
uint t, uint rounds, uint delta)
{
uint i, j;
priv.H.resize (block_count);
if (wi > block_size / 2) return 1; //safety
/*
* Trick. Cyclomatic matrix of size n is invertible if a
* polynomial that's made up from its first row is coprime to
* (x^n-1), the polynomial inversion and matrix inversion are
* then isomorphic.
*/
gf2m gf;
gf.create (1); //binary
polynomial xmm1; //x^m-1
xmm1.resize (block_size + 1, 0);
xmm1[0] = 1;
xmm1[block_size] = 1;
polynomial last_inv_H;
for (;;) {
//retry generating the rightmost block until it is invertible
polynomial g;
g.resize (block_size, 0);
for (i = 0; i < wi; ++i)
for (uint pos = rng.random (block_size);
g[pos] ? 1 : (g[pos] = 1, 0);
pos = rng.random (block_size));
//try if it is coprime to (x^n-1)
polynomial gcd = g.gcd (xmm1, gf);
if (!gcd.one()) continue; //it isn't.
//if it is, save it to matrix (in "reverse" order for columns)
priv.H[block_count - 1].resize (block_size, 0);
for (i = 0; i < block_size && i < g.size(); ++i)
priv.H[block_count - 1][i] = g[ (-i) % block_size];
//invert it, save for later and succeed.
g.inv (xmm1, gf);
last_inv_H = g;
break;
}
//generate the rests of matrix blocks, fill the G right away.
pub.G.resize (block_count - 1);
for (i = 0; i < block_count - 1; ++i) {
polynomial hi;
hi.resize (block_size, 0);
//generate the polynomial corresponding to the first row
for (j = 0; j < wi; ++j)
for (uint pos = rng.random (block_size);
hi[pos] ? 1 : (hi[pos] = 1, 0);
pos = rng.random (block_size));
//save it to H
priv.H[i].resize (block_size);
for (j = 0; j < block_size; ++j) priv.H[i][j] = hi[ (-j) % block_size];
//compute inv(H[last])*H[i]
hi.mult (last_inv_H, gf);
hi.mod (xmm1, gf);
//save it to G
pub.G[i].resize (block_size);
for (j = 0; j < block_size; ++j) pub.G[i][j] = hi[j % block_size];
}
//save the target params
pub.t = priv.t = t;
priv.rounds = rounds;
priv.delta = delta;
return 0;
}
int privkey::prepare()
{
return 0;
}
int pubkey::encrypt (const bvector& in, bvector&out, prng&rng)
{
uint s = cipher_size();
if (t > s) return 1;
//create the error vector
bvector e;
e.resize (s);
for (uint i = 0; i < t; ++i)
for (uint pos = rng.random (s);
e[pos] ? 1 : (e[pos] = 1, 0);
pos = rng.random (s));
return encrypt (in, out, e);
}
int pubkey::encrypt (const bvector&in, bvector&out, const bvector&errors)
{
uint ps = plain_size();
if (in.size() != ps) return 1;
uint bs = G[0].size();
for (uint i = 1; i < G.size(); ++i) if (G[i].size() != bs) return 1; //prevent mangled keys
//first, the checksum part
bvector bcheck;
//G stores first row(s) of the circulant matrix blocks, proceed row-by-row and construct the checkum
for (uint i = 0; i < ps; ++i)
if (in[i]) bcheck.rot_add (G[ (i % ps) / bs], i % bs);
//compute the ciphertext
out = in;
out.append (bcheck);
out.add (errors);
return 0;
}
int privkey::decrypt (const bvector & in, bvector & out)
{
bvector tmp_errors;
return decrypt (in, out, tmp_errors);
}
#include <vector>
#include "iohelpers.h"
#include "ios.h"
int privkey::decrypt (const bvector & in_orig, bvector & out, bvector & errors)
{
uint i;
uint cs = cipher_size();
if (in_orig.size() != cs) return 1;
uint bs;
bs = H[0].size();
/*
* probabilistic decoding!
*/
//compute the syndrome first
bvector syndrome;
syndrome.resize (bs, 0);
bvector in = in_orig; //we will modify it
for (i = 0; i < cs; ++i) if (in[i])
syndrome.rot_add (H[i / bs], (cs - i) % bs);
//minimize counts of unsatisfied equations by flipping
std::vector<uint> unsatisfied;
unsatisfied.resize (cs, 0);
for (i = 0; i < rounds; ++i) {
uint bit, max_unsat;
bvector tmp;
max_unsat = 0;
for (bit = 0; bit < cs; ++bit) {
tmp.fill_zeros();
tmp.rot_add (H[bit / bs], (cs - bit) % bs);
unsatisfied[bit] = tmp.and_hamming_weight (syndrome);
if (unsatisfied[bit] > max_unsat) max_unsat = unsatisfied[bit];
}
//TODO what about timing attacks?
if (!max_unsat) break;
uint threshold = 0;
if (max_unsat > delta) threshold = max_unsat - delta;
//TODO also timing (but it gets pretty statistically hard here I guess)
uint flipped = 0;
for (bit = 0; bit < cs; ++bit)
if (unsatisfied[bit] > threshold) {
in[bit] = !in[bit];
syndrome.rot_add (H[bit / bs], (cs - bit) % bs);
++flipped;
}
}
if (i == rounds) return 2; //we simply failed
errors = in_orig;
errors.add (in); //get the difference
out (errors);
out = in;
out.resize (plain_size());
return 0;
}

90
src/mce_qcmdpc.h Normal file
View file

@ -0,0 +1,90 @@
/*
* This file is part of Codecrypt.
*
* Codecrypt is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Codecrypt is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Codecrypt. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _ccr_mce_qcmdpc_h_
#define _ccr_mce_qcmdpc_h_
#include <vector>
#include <stdint.h>
#include "bvector.h"
#include "matrix.h"
#include "prng.h"
#include "sencode.h"
#include "types.h"
/*
* quasi-cyclic MDPC McEliece
* Implemented accordingly to the paper by Misoczki, Tillich, Sendrier and Barreto.
*/
namespace mce_qcmdpc
{
class privkey
{
public:
matrix H; //elems = _cols_ of H blocks (at least 2)
uint t;
uint rounds;
uint delta;
int decrypt (const bvector&, bvector&);
int decrypt (const bvector&, bvector&, bvector&);
int prepare();
uint cipher_size() {
return H[0].size() * H.size();
}
uint plain_size() {
return H[0].size() * (H.size() - 1);
}
uint error_count() {
return t;
}
sencode* serialize();
bool unserialize (sencode*);
};
class pubkey
{
public:
matrix G; //elems = top lines of right-side G blocks
uint t; //error count
int encrypt (const bvector&, bvector&, prng&);
int encrypt (const bvector&, bvector&, const bvector&);
uint cipher_size() {
return G[0].size() * (G.size() + 1);
}
uint plain_size() {
return G[0].size() * G.size();
}
uint error_count() {
return t;
}
sencode* serialize();
bool unserialize (sencode*);
};
int generate (pubkey&, privkey&, prng&, uint blocksize, uint blocks, uint wi,
uint t, uint rounds, uint delta);
}
#endif

View file

@ -23,9 +23,8 @@
#include "gf2m.h"
#include "polynomial.h"
#include "permutation.h"
#include "mce.h"
#include "nd.h"
#include "mce_qd.h"
#include "mce_qcmdpc.h"
#include "fmtseq.h"
#include "message.h"
#include "hashfile.h"
@ -66,8 +65,12 @@ sencode* bvector::serialize()
uint ss = (size() + 7) / 8;
std::string bytes;
bytes.resize (ss, '\0');
for (uint i = 0; i < size(); ++i)
if (item (i)) bytes[i / 8] |= 1 << (i % 8);
//the padding of each vector is zero, we can stuff the bytes right in. Just make it sure here:
fix_padding();
for (size_t i = 0; i < size(); i += 8)
bytes[i >> 3] = (_data[i >> 6] >> ( ( (i >> 3) & 7) << 3)) & 0xff;
sencode_list*l = new sencode_list;
l->items.push_back (new sencode_int (size()));
l->items.push_back (new sencode_bytes (bytes));
@ -84,15 +87,14 @@ bool bvector::unserialize (sencode* s)
if (bytes->b.size() != ( (size->i + 7) / 8)) return false;
clear();
resize (size->i, 0);
for (i = 0; i < size->i; ++i)
if ( (bytes->b[i / 8] >> (i % 8)) & 1)
item (i) = 1;
for (i = 0; i < _size; i += 8)
_data[i >> 6] |= ( (uint64_t) (unsigned char) bytes->b[i >> 3]) << ( ( (i >> 3) & 7) << 3);
/*
* the important part. verify that padding is always zero, because
* sencode serialization must be bijective
*/
for (; i < 8 * bytes->b.size(); ++i)
for (i = _size; i < 8 * bytes->b.size(); ++i)
if ( (bytes->b[i / 8] >> (i % 8)) & 1)
return false;
@ -368,6 +370,67 @@ bool fmtseq::privkey::tree_stk_item::unserialize (sencode*s)
}
sencode* mce_qcmdpc::pubkey::serialize()
{
sencode_list*l = new sencode_list;
l->items.resize (3);
l->items[0] = new sencode_bytes (PUBKEY_IDENT "QCMDPC-MCE");
l->items[1] = new sencode_int (t);
l->items[2] = G.serialize();
return l;
}
bool mce_qcmdpc::pubkey::unserialize (sencode* s)
{
sencode_list*CAST_LIST (s, l);
if (l->items.size() != 3) return false;
sencode_bytes*CAST_BYTES (l->items[0], ident);
if (ident->b.compare (PUBKEY_IDENT "QCMDPC-MCE")) return false;
sencode_int*CAST_INT (l->items[1], p);
t = p->i;
if (!G.unserialize (l->items[2])) return false;
return true;
}
sencode* mce_qcmdpc::privkey::serialize()
{
sencode_list*l = new sencode_list;
l->items.resize (5);
l->items[0] = new sencode_bytes (PRIVKEY_IDENT "QCMDPC-MCE");
l->items[1] = new sencode_int (t);
l->items[2] = new sencode_int (rounds);
l->items[3] = new sencode_int (delta);
l->items[4] = H.serialize();
return l;
}
bool mce_qcmdpc::privkey::unserialize (sencode*s)
{
sencode_list*CAST_LIST (s, l);
if (l->items.size() != 5) return false;
sencode_bytes*CAST_BYTES (l->items[0], ident);
if (ident->b.compare (PRIVKEY_IDENT "QCMDPC-MCE")) return false;
sencode_int*CAST_INT (l->items[1], p);
t = p->i;
CAST_INT (l->items[2], p);
rounds = p->i;
CAST_INT (l->items[3], p);
delta = p->i;
if (!H.unserialize (l->items[4])) return false;
return true;
}
sencode* fmtseq::privkey::serialize()
{
/*