返回顶部

收藏

ElGamal密码算法

更多

ElGamal密码算法

ElGamal.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;

namespace ElGamalProgram
{
    class ElGamal
    {
        private const int MAXINT64LEN = sizeof(Int64);//用来作为读取的单位长度
        private const string tempPrePadding = "_elgpad";//用来生成paded文件的文件名
        private const string tempPreTransforming = "_elgtrans";//用来生成transformed文件的文件名
        private const int BITSLEN = 60;//密钥的长度
        private RandomPrimeGenerator r = new RandomPrimeGenerator();//用来生成随机数,及进行其他运算

        private Int64 p;    //大素数
        private Int64 a;    //生成元
        private Int64 sk;   //私钥
        private Int64 pk;   //公钥

        public ElGamal(Int64 p, Int64 sk)
        {
            this.p = p;
            this.sk = sk;

        }

        public void init4Encode(Int64 a)
        {
            this.a = a;
            this.pk = r.modPower(a, sk, p);
        }

        //将输入的文件进行变换之后,再加密,输出到输出文件中
        public void Encode(string inputFile, string outputFile)
        {
            string path = Path.GetDirectoryName(inputFile);
            string name = Path.GetFileName(inputFile);
            string transformedFile = path + "\\"+tempPreTransforming + name;
            prepare4Encoding(inputFile, transformedFile, p);
            ElGamalEncode(transformedFile, outputFile);
            File.Delete(transformedFile);
        }
        //将输入的文件进行变换之后,再解密,输出到输出文件中
        public void Decode(string inputFile, string outputFile)
        {
            string path = Path.GetDirectoryName(inputFile);
            string name = Path.GetFileName(inputFile);
            string decodedFile = path +"\\"+ tempPrePadding+name;
            ElGamalDecode(inputFile, decodedFile);
            postDecoding(decodedFile, outputFile, p);
            File.Delete(decodedFile);
        }
        //对于已经经过变换之后的文件,直接进行加密
        private void ElGamalEncode(string inputFile, string outputFile)
        {
            FileStream finput = openFile(inputFile);
            if (finput == null)
                return;
            FileStream foutput = createFile(outputFile);
            if (foutput == null)
                return;

            Int64 m;
            while ((m = inputInt64(finput)) != -1)
            {
                Int64 k = r.nextInt64(0, p - 1);
                Int64 y1 = r.modPower(a, k, p);
                byte[] temp = BitConverter.GetBytes(y1);
                foutput.Write(temp, 0, MAXINT64LEN);
                Int64 pk1 = r.modPower(pk, k, p);
                Int64 y2 = r.multiplyMod(m, pk1, p);
                foutput.Write(BitConverter.GetBytes(y2), 0, MAXINT64LEN);
            }
            finput.Close();
            foutput.Close();
        }

        //将变换之后的文件进行直接解密
        private void ElGamalDecode(string inputFile, string outputFile)
        {
            FileStream finput = openFile(inputFile);
            if (finput == null)
                return;
            FileStream foutput = createFile(outputFile);
            if (foutput == null)
                return;
            Int64 y1;
            while ((y1 = inputInt64(finput)) != -1)
            {
                Int64 y2 = inputInt64(finput);
                Int64 t = r.modPower(y1, sk, p);
                t = r.reverse(t, p);
                Int64 m = r.multiplyMod(y2, t, p);
                foutput.Write(BitConverter.GetBytes(m), 0, MAXINT64LEN);
            }
            finput.Close();
            foutput.Close();
        }

        //将二进制串进行加密,结果存放在output1和output2中 
        public void ElGamalEncodeBits(Int64 input, out Int64 output1, out Int64 output2)
        {
            Int64 k = r.nextInt64(0, p - 1);
            output1 = r.modPower(a, k, p);
            Int64 pk1 = r.modPower(pk, k, p);
            output2 = r.multiplyMod(input, pk1, p);
        }
        //将二进制串进行解密,结果存放在input中
        public void ElGamalDecodeBits(out Int64 input, Int64 output1, Int64 output2)
        {
            Int64 t = r.modPower(output1, sk, p);
            t = r.reverse(t, p);
            input = r.multiplyMod(output2, t, p);
        }
        //从文件流finput中读入一个Int64型数据
        private Int64 inputInt64(FileStream finput)
        {
            byte[] temp = new byte[MAXINT64LEN];
            int count = finput.Read(temp, 0, MAXINT64LEN);
            if (count == 0)
                return -1;
            Int64 result = BitConverter.ToInt64(temp, 0);
            return result;
        }
        //为加密做准备
        private void prepare4Encoding(string inputFile, string transformedFile, Int64 p0)
        {
            FileStream finput = openFile(inputFile);
            if (finput == null)
                return;
            string path = Path.GetDirectoryName(inputFile);
            string name = Path.GetFileName(inputFile);
            string paddedFile = path + "\\"+tempPrePadding + name;
            FileStream fPadded = createFile(paddedFile);
            if (fPadded == null)
                return;
            FileStream fTransformed = createFile(transformedFile);
            if (fTransformed == null)
                return;
            padding_Transform(finput, fPadded, fTransformed, p0);
            File.Delete(paddedFile);
        }
        //在解密完成之后,进行变换
        private void postDecoding(string decodedFile, string depaddedFile, Int64 p0)
        {
            FileStream fDecoded = openFile(decodedFile);
            if (fDecoded == null)
                return;
            string path = Path.GetDirectoryName(decodedFile);
            string name = Path.GetFileName(decodedFile);
            string detransformedFile = path + "\\"+tempPreTransforming + name;
            FileStream fDetransformed = createFile(detransformedFile);
            if (fDetransformed == null)
                return;
            FileStream fDepadded = createFile(depaddedFile);
            if (fDepadded == null)
                return;
            detransform_Depadding(fDecoded, fDetransformed, fDepadded, p0);
            File.Delete(detransformedFile);
        }
        //辅助函数
        private FileStream openFile(string fileName)
        {
            FileStream file = new FileStream(fileName, FileMode.Open);
            if (!file.CanRead)
            {
                string complain = "不能打开文件" + file + "!";
                errorComplain(complain);
                file.Close();
                return null;
            }
            return file;
        }
        //辅助函数
        private FileStream createFile(string fileName)
        {
            FileStream file = new FileStream(fileName, FileMode.Create);
            if (!file.CanWrite)
            {
                string complain = "不能创建文件" + file + "!";
                errorComplain(complain);
                file.Close();
                return null;
            }
            return file;
        }
        //辅助函数
        private void errorComplain(string complain)
        {
            MessageBox.Show(complain, "Error");
        }
        //进行padding的变换
        private void padding_Transform(FileStream finput, FileStream fPadded, FileStream fTransformed, Int64 p0)
        {
            finput.CopyTo(fPadded);
            encodePadding(fPadded);
            fPadded.Seek(0, SeekOrigin.Begin);
            encodeTransform(fPadded, fTransformed, p0);

            finput.Close();
            fPadded.Close();
            fTransformed.Close();
        }
        //逆变换
        private void detransform_Depadding(FileStream fDecoded, FileStream fDetransformed, FileStream fDepadded, Int64 p0)
        {
            decodeDeTransform(fDecoded, fDetransformed, p0);
            fDetransformed.Seek(0, SeekOrigin.Begin);
            decodeDePadding(fDetransformed, fDepadded, p0);

            fDecoded.Close();
            fDetransformed.Close();
            fDepadded.Close();
        }
        //padding
        private void encodePadding(FileStream foutput)
        {
            Int64 size = foutput.Length;
            Int64 residue;
            residue = size % MAXINT64LEN;
            residue = MAXINT64LEN - residue;
            for (Int64 i = 0; i < residue; i++)
                foutput.WriteByte(0);
            byte[] temp = BitConverter.GetBytes(size);
            foutput.Write(temp, 0, MAXINT64LEN);
        }

        private void encodeTransform(FileStream fPadded, FileStream fTransformed, Int64 p0)
        {
            UInt64 p = (UInt64)p0;
            byte[] tempForInputM = new byte[MAXINT64LEN];
            byte[] tempForOutputM;
            while (fPadded.Read(tempForInputM, 0, MAXINT64LEN) != 0)
            {
                UInt64 m = BitConverter.ToUInt64(tempForInputM, 0);
                tempForOutputM = BitConverter.GetBytes(m / p + 1);
                fTransformed.Write(tempForOutputM, 0, MAXINT64LEN);
                tempForOutputM = BitConverter.GetBytes(m % p + 1);
                fTransformed.Write(tempForOutputM, 0, MAXINT64LEN);
            }
        }
        private void decodeDeTransform(FileStream fDecoded, FileStream fDetransformed, Int64 p0)
        {
            UInt64 p = (UInt64)p0;
            byte[] tempForOutputM = new byte[MAXINT64LEN];
            while (fDecoded.Read(tempForOutputM, 0, MAXINT64LEN) != 0)
            {
                UInt64 m1 = BitConverter.ToUInt64(tempForOutputM, 0);
                fDecoded.Read(tempForOutputM, 0, MAXINT64LEN);
                UInt64 m2 = BitConverter.ToUInt64(tempForOutputM, 0);
                m1 -= 1;
                m2 -= 1;
                UInt64 m = m1 * p + m2;
                fDetransformed.Write(BitConverter.GetBytes(m), 0, MAXINT64LEN);
            }
        }
        private void decodeDePadding(FileStream fDetransformed, FileStream fDepadded, Int64 p0)
        {
            UInt64 p = (UInt64)p0;
            byte[] tempForOutputM1 = new byte[MAXINT64LEN];
            byte[] tempForOutputM2 = new byte[MAXINT64LEN];
            Int64 size = fDetransformed.Length;
            while (fDetransformed.Read(tempForOutputM1, 0, MAXINT64LEN) != 0)
            {
                //如果是倒数第二个字符
                if (fDetransformed.Position == size - 1 * MAXINT64LEN)
                {
                    UInt64 padding = BitConverter.ToUInt64(tempForOutputM1, 0);
                    fDetransformed.Read(tempForOutputM2, 0, MAXINT64LEN);
                    UInt64 fileLen = BitConverter.ToUInt64(tempForOutputM2, 0);
                    UInt64 residue = fileLen % MAXINT64LEN;
                    for (UInt64 i = 0; i < residue; i++)
                        fDepadded.WriteByte(tempForOutputM1[i]);
                    return;
                }
                else
                {
                    fDepadded.Write(tempForOutputM1, 0, MAXINT64LEN);
                }
            }

        }
        static void Main(string[] args)
        {
            RandomPrimeGenerator r = new RandomPrimeGenerator();
            Int64 p = r.RandomSafePrime(60);
            Int64 a = r.generator(p);
            Int64 k = r.nextInt64(0, p-1);
            Int64 sk = r.nextInt64(1, p - 1);
            ElGamal e = new ElGamal(p, sk);
            Int64 output1 = 0, output2 = 0;
            e.ElGamalEncodeBits(1243424,out output1,out output2);
            Console.WriteLine(output1);
            Console.WriteLine(output2);
        }
    }
}

标签:c#

收藏

0人收藏

支持

0

反对

0

发表评论