Ejemplo n.º 1
0
        /// <summary>
        /// Encode a number between 0 and (n|t) (binomial coefficient) into a binary vector of length n with weight t.
        /// <para>The number is given as a byte array. Only the first s bits are used, where s = floor[log(n|t)].</para>
        /// </summary>
        ///
        /// <param name="N">The "n" integer</param>
        /// <param name="T">The "t" integer</param>
        /// <param name="M">The message as a byte array</param>
        ///
        /// <returns>The encoded message as GF2Vector</returns>
        public static GF2Vector Encode(int N, int T, byte[] M)
        {
            if (N < T)
            {
                throw new ArgumentException("n < t");
            }

            // compute the binomial c = (n|t)
            BigInteger c = BigMath.Binomial(N, T);
            // get the number encoded in m
            BigInteger i = new BigInteger(1, M);

            // compare
            if (i.CompareTo(c) >= 0)
            {
                throw new ArgumentException("Encoded number too large.");
            }

            GF2Vector result = new GF2Vector(N);
            int       nn     = N;
            int       tt     = T;

            for (int j = 0; j < N; j++)
            {
                c = c.Multiply(BigInteger.ValueOf(nn - tt)).Divide(BigInteger.ValueOf(nn));
                nn--;

                if (c.CompareTo(i) <= 0)
                {
                    result.SetBit(j);
                    i = i.Subtract(c);
                    tt--;

                    if (nn == tt)
                    {
                        c = ONE;
                    }
                    else
                    {
                        c = (c.Multiply(BigInteger.ValueOf(tt + 1))).Divide(BigInteger.ValueOf(nn - tt));
                    }
                }
            }

            return(result);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Decode a binary vector of length n and weight t into a number between 0 and (n|t) (binomial coefficient).
        /// <para>The result is given as a byte array of length floor[(s+7)/8], where s = floor[log(n|t)].</para>
        /// </summary>
        ///
        /// <param name="N">The "n" integer</param>
        /// <param name="T">The "t" integer</param>
        /// <param name="GVector">The binary vector</param>
        ///
        /// <returns>The decoded vector as a byte array</returns>
        public static byte[] Decode(int N, int T, GF2Vector GVector)
        {
            if ((GVector.Length != N) || (GVector.HammingWeight() != T))
            {
                throw new ArgumentException("vector has wrong length or hamming weight");
            }

            int[]      vecArray = GVector.VectorArray;
            BigInteger bc       = BigMath.Binomial(N, T);
            BigInteger d        = ZERO;
            int        nn       = N;
            int        tt       = T;

            for (int i = 0; i < N; i++)
            {
                bc = bc.Multiply(BigInteger.ValueOf(nn - tt)).Divide(BigInteger.ValueOf(nn));
                nn--;

                int q = i >> 5;
                int e = vecArray[q] & (1 << (i & 0x1f));
                if (e != 0)
                {
                    d = d.Add(bc);
                    tt--;

                    if (nn == tt)
                    {
                        bc = ONE;
                    }
                    else
                    {
                        bc = bc.Multiply(BigInteger.ValueOf(tt + 1)).Divide(BigInteger.ValueOf(nn - tt));
                    }
                }
            }

            return(BigIntUtils.ToMinimalByteArray(d));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Compute a message representative of a message given as a vector of length <c>n</c> bit and of hamming weight <c>t</c>.
        /// <para>The result is a byte array of length <c>(s+7)/8</c>, where <c>s = floor[log(n|t)]</c>.</para>
        /// </summary>
        ///
        /// <param name="N">The "n" integer</param>
        /// <param name="T">The "t" integer</param>
        /// <param name="M">The message vector as a byte array</param>
        ///
        /// <returns>A message representative for <c>m</c></returns>
        public static byte[] SignConversion(int N, int T, byte[] M)
        {
            if (N < T)
            {
                throw new ArgumentException("n < t");
            }

            BigInteger bc = BigMath.Binomial(N, T);
            // finds s = floor[log(binomial(n,t))]
            int s = bc.BitLength - 1;
            // s = sq*8 + sr;
            int sq = s >> 3;
            int sr = s & 7;

            if (sr == 0)
            {
                sq--;
                sr = 8;
            }

            // n = nq*8+nr;
            int nq = N >> 3;
            int nr = N & 7;

            if (nr == 0)
            {
                nq--;
                nr = 8;
            }

            // take s bit from m
            byte[] data = new byte[nq + 1];
            if (M.Length < data.Length)
            {
                Array.Copy(M, 0, data, 0, M.Length);

                for (int i = M.Length; i < data.Length; i++)
                {
                    data[i] = 0;
                }
            }
            else
            {
                Array.Copy(M, 0, data, 0, nq);
                int h = (1 << nr) - 1;
                data[nq] = (byte)(h & M[nq]);
            }

            BigInteger d  = ZERO;
            int        nn = N;
            int        tt = T;

            for (int i = 0; i < N; i++)
            {
                bc = (bc.Multiply(new BigInteger(IntUtils.ToString(nn - tt)))).Divide(new BigInteger(IntUtils.ToString(nn)));
                nn--;

                int q = IntUtils.URShift(i, 3);
                int r = i & 7;
                r = 1 << r;
                byte e = (byte)(r & data[q]);

                if (e != 0)
                {
                    d = d.Add(bc);
                    tt--;
                    if (nn == tt)
                    {
                        bc = ONE;
                    }
                    else
                    {
                        bc = (bc.Multiply(new BigInteger(IntUtils.ToString(tt + 1)))).Divide(new BigInteger(IntUtils.ToString(nn - tt)));
                    }
                }
            }

            byte[] result = new byte[sq + 1];
            byte[] help   = d.ToByteArray();
            if (help.Length < result.Length)
            {
                Array.Copy(help, 0, result, 0, help.Length);

                for (int i = help.Length; i < result.Length; i++)
                {
                    result[i] = 0;
                }
            }
            else
            {
                Array.Copy(help, 0, result, 0, sq);
                result[sq] = (byte)(((1 << sr) - 1) & help[sq]);
            }

            return(result);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Encrypt a plain text message
        /// </summary>
        ///
        /// <param name="Input">The plain text</param>
        ///
        /// <returns>The cipher text</returns>
        public byte[] Encrypt(byte[] Input)
        {
            if (!_isEncryption)
            {
                throw new CryptoAsymmetricSignException("KobaraImaiCipher:Encrypt", "The cipher is not initialized for encryption!", new ArgumentException());
            }

            int c2Len = _dgtEngine.DigestSize;
            int c4Len = _K >> 3;
            int c5Len = (BigMath.Binomial(_N, _T).BitLength - 1) >> 3;
            int mLen  = c4Len + c5Len - c2Len - MPKCINFO.Length;

            if (Input.Length > mLen)
            {
                mLen = Input.Length;
            }

            int c1Len = mLen + MPKCINFO.Length;
            int c6Len = c1Len + c2Len - c4Len - c5Len;

            // compute (m||const)
            byte[] mConst = new byte[c1Len];
            Array.Copy(Input, 0, mConst, 0, Input.Length);
            Array.Copy(MPKCINFO, 0, mConst, mLen, MPKCINFO.Length);

            // generate random r of length c2Len bytes
            byte[] r = new byte[c2Len];
            _rndEngine.GetBytes(r);

            byte[] c1;
            // get PRNG object ToDo:
            //DigestRandomGenerator sr0 = new DigestRandomGenerator(new SHA1Digest()); //why bc, why?
            using (KDF2Drbg sr0 = new KDF2Drbg(GetDigest(_cprParams.Digest)))
            {
                // seed PRNG with r'
                sr0.Initialize(r);
                // generate random sequence ...
                c1 = new byte[c1Len];
                sr0.Generate(c1);
            }

            // ... and XOR with (m||const) to obtain c1
            for (int i = c1Len - 1; i >= 0; i--)
            {
                c1[i] ^= mConst[i];
            }

            // compute H(c1) ...
            byte[] c2 = new byte[_dgtEngine.DigestSize];
            _dgtEngine.BlockUpdate(c1, 0, c1.Length);
            _dgtEngine.DoFinal(c2, 0);

            // ... and XOR with r
            for (int i = c2Len - 1; i >= 0; i--)
            {
                c2[i] ^= r[i];
            }

            // compute (c2||c1)
            byte[] c2c1 = ByteUtils.Concatenate(c2, c1);

            // split (c2||c1) into (c6||c5||c4), where c4Len is k/8 bytes, c5Len is
            // floor[log(n|t)]/8 bytes, and c6Len is c1Len+c2Len-c4Len-c5Len (may be 0).
            byte[] c6 = new byte[0];
            if (c6Len > 0)
            {
                c6 = new byte[c6Len];
                Array.Copy(c2c1, 0, c6, 0, c6Len);
            }

            byte[] c5 = new byte[c5Len];
            Array.Copy(c2c1, c6Len, c5, 0, c5Len);
            byte[] c4 = new byte[c4Len];
            Array.Copy(c2c1, c6Len + c5Len, c4, 0, c4Len);
            // convert c4 to vector over GF(2)
            GF2Vector c4Vec = GF2Vector.OS2VP(_K, c4);
            // convert c5 to error vector z
            GF2Vector z = CCA2Conversions.Encode(_N, _T, c5);

            // compute encC4 = E(c4, z)
            byte[] encC4 = CCA2Primitives.Encrypt((MPKCPublicKey)_asmKey, c4Vec, z).GetEncoded();

            // if c6Len > 0 return (c6||encC4)
            if (c6Len > 0)
            {
                return(ByteUtils.Concatenate(c6, encC4));
            }

            // else, return encC4
            return(encC4);
        }