前段时间选修信息安全实验课,为了完成课程目标,对NTRU加密算法进行了简单的编程实现。使用c#编程语言,完成了一个加解密winform应用程序。
首先对NTRU加解密算法简答的介绍一下。基于寻找格中最短向量问题的快速的加密算法。在很多领域内有着很广泛的应用。NTRU算法的加解密过程如下:
秘钥生成:
加密过程:
解密过程:
编程的主要思想就是将环中的多项式用简单的数组表示,加解密过程中所用到的多项式乘法和多项式加法都在数组中进行。特殊的,多项式的逆用单独的函数进行求解。编程过程中用到的主要算法有:扩展的欧几里得算法(数求模与其互素的数逆);牛顿迭代算法(多项式求模多项式的逆);卷积算法(截断环内的多项式乘法)。
下面就贴上我写的源代码和大家讨论一下,c#编程都是自学,有错误的地方,希望大家可以指出。
先贴一张成形后的图片吧!
布局也是很简单,这里就不做其他赘述了。
下面是主要算法的实现:
/// <summary>
/// 求多项式的逆
/// </summary>
/// <param name="a">多项式</param>
/// <param name="N">多项式最高次</param>
/// <param name="p">模p</param>
/// <returns></returns>
public int[] InversePoly(int[] a, int N, int q)
{
int k = 0;
int[] b = new int[N];
int[] c = new int[N];
int[] f = new int[N];
int[] g = new int[N + 1];
f = a;
g[N] = 1; g[0] = -1; b[0] = 1;
while (true)
{
while (f[0] == 0)
{
for (int i = 1; i <= f.Length - 1; i++)
{
f[i - 1] = f[i];
}
for (int i = c.Length - 1; i > 0; i--)
{
c[i] = c[i - 1];
}
f[f.Length - 1] = 0;
c[0] = 0;
k++;
}
if (deg(f) == 0)
{
for (int i = 0; i < N; i++)
{
b[i] = Ix(f[0], q) * b[i];
b[i] = b[i] % q;
}
int[] b1 = new int[N];
for (int i = 0; i < N; i++)
{
b1[i] = b[i];
if (b1[i] < 0)
{
b1[i] = b1[i] + q;
}
}
if (k > N)
{
for (int i = 0; i < N; i++)
{
b[i] = b1[(k - N + i) % N];
// b[(i + k - N) % N] = (b1[(2 * k - 3*N + i) % N]);
}
}
else
{
for (int i = 0; i <= k - 1; i++)
{
b[N - k + i] = b[i] % q;
}
for (int i = k; i <= N - 1; i++)
{
b[i - k] = b[i] % q;
}
}
return b;
}
if (deg(f) < deg(g))
{
int[] t = new int[N];
t = f;
f = g;
g = t;
t = b;
b = c;
c = t;
}
int u = 0;
if (g[0] < 0)
{
int t = 0;
t = g[0];
t = (t + q) % q;
int Inx = Ix(t, q);
u = (f[0] * Inx) % q;
}
else
{
int Inx = Ix(g[0], q);
u = (f[0] * Inx) % q;
}
for (int i = 0; i < N; i++)
{
f[i] = (f[i] - u * g[i]) % q;
b[i] = (b[i] - u * c[i]) % q;
}
}
// return b;
}
/// <summary>
/// x模m的逆
/// </summary>
/// <param name="x"></param>
/// <param name="m"></param>
/// <returns></returns>
public int Ix(int m, int n)//扩展的欧几里得算法
{
int a, b, c, d, t;
int ap, bp;
int q, r;
ap = b = 1;
a = bp = 0;
c = m;
d = n;
while (d != 0)
{
q = c / d;
r = c % d;
c = d;
d = r;
t = ap;
ap = a;
a = t - q * a;
t = bp;
bp = b;
b = t - q * b;
}
if (ap < 0)
{
ap = ap + n;
}
return ap;
}
/// <summary>
/// 多项式的乘积
/// </summary>
/// <param name="a">多项式a</param>
/// <param name="b">多项式b</param>
/// <param name="N">标准参数</param>
/// <param name="m">模m</param>
/// <returns></returns>
public int[] MultiPloy(int[] a, int[] b, int N, int m)
{
int[] c = new int[N];
// int[] c = new int[N];
for (int i = (N - 1); i >= 0; i--)
{
c[i] = 0;
}
for (int i = (N - 1); i >= 0; i--)
{
int K = 0;
for (int j = 0; j <= i; j++)
{
c[i] += a[j] * b[i - j];
c[i] = c[i] % m;
}
for (int j = 1; j <= N - 1 - i; j++)
{
K += a[i + j] * b[N - j];
K = K % m;
}
c[i] = c[i] += K;
c[i] = c[i] % m;
}
return c;
}
以上是加解密过程中所用到的算法。算法中要求的输入为01串,但是在实际的加解密的过程中输入的为要加密的明文,解密过程也是一样的。所以就需要在加密过程中将明文转化为01串,而在解密过程中,将01串转化为明文输出。
我主要采用的是将明文转化为ASCII码的方式实现转化。下面是具体的实现代码
/// <summary>
/// 将8bit0,1 串转化成字母串
/// </summary>
/// <param name="bitString">将8bit0,1 串</param>
/// <returns>字母串</returns>
private static string bit01ToWord(string bitString)
{
//将8位的二进制串转化为ASCII
//string teststring = WordTo8bit01("I have a dog.");
string[] sub = new string[bitString.Length / 8];
int[] count = new int[bitString.Length / 8];
for (int i = 0; i < bitString.Length / 8; i++)
{
sub[i] = bitString.Substring(i * 8, 8);
try
{ count[i] = Convert.ToInt32(sub[i], 2);
}
catch( Exception e)
{
MessageBox.Show("输入参数异常");
}
//Console.WriteLine("{0}ahifahisdfiasdhfasdfasdfasd", count[i]);
}
//将ASSII转化为字母\
string strCharacter = null;
for (int i = 0; i < count.Length; i++)
{
if (count[i] >= 0 && count[i] <= 255)
{
ASCIIEncoding asciiEncoding = new ASCIIEncoding();
byte[] byteArray = new byte[] { (byte)count[i] };
strCharacter += asciiEncoding.GetString(byteArray);
}
}
return strCharacter;
}
/// <summary>
/// 将字母串转化成8bit0,1 串
/// </summary>
/// <param name="str">字母串</param>
/// <returns>8bit0,1 串</returns>
public static string WordTo8bit01(string str)
{
//将字母转化成ASCII
//str = "I have a dog AB Cabc*+/.";
ASCIIEncoding ae = new ASCIIEncoding();
byte[] ByteArray = ae.GetBytes(str);
//for (int i = 0; i < ByteArray.Length; i++)
//{
// Console.Write("{0} ", ByteArray[i]);
//} Console.WriteLine("");
//将ASCII转化成8位的二进制串
string s = null;
for (int i = 0; i < ByteArray.Length; i++)
{
s += Convert.ToString(ByteArray[i], 2).PadLeft(8, '0');
//Console.Write(s);
}
return s;
}
以上就是我的编程过程中的主要代码实现。希望可以帮到有需要的人,同时有什么问题,希望大家可以指出,帮助我进步。。第一次发,很多地方不是很熟悉,希望大家见谅。