Hỏi đáp

Chia sẻ kiến thức, cùng nhau phát triển

C# hỗ trợ mật mã hill

14:01 02-05-2017 8.059 lượt xem 4 bình luận 08:52 03-05-2017

Mình có dòng code sau:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Hill_Cipher
{
    class Program
    {
        static void Main(string[] args)
        {   //Khai báo
            int i, j, sum = 0, end = 0;
            int[,] mtrx = new int[25, 25];
            int[,] ans = new int[25, 1];
            int m ;
            string text = "";
            //m
            Console.WriteLine("Nhap m:");
            m = int.Parse(Console.ReadLine());
            //Nhập mã khóa
            Console.WriteLine("Nhap key:");
            for (i = 0; i < m; i++)
            {
                for (j = 0; j < m; j++)
                {
                    Console.Write("Phan tu - [{0}],[{1}]: ", i, j);
                    mtrx[i, j] = int.Parse(Console.ReadLine());
                }
            }  
            //Input
            Console.WriteLine("Nhap van ban");
            Console.Write("\n");
            text = Console.ReadLine();
            Console.Write("\n");
            char[] txt = text.ToCharArray();
            end = txt.Length;
            for (i = 0; i < end; i++)
            {
                    txt[i] = Convert.ToChar(txt[i]-'a');
            }
            //Ma trận
            for (i = 0; i < end; i++)
            {
                sum = 0;
                for (j = 0; j < end; j++)
                {
                    sum += mtrx[i, j] * (int)txt[j];
                }
                ans[i, 0] = sum;
            }
            //Output
            Console.Write("Van ban da ma hoa:");
            for (i = 0; i < end; i++)
            {
                char cipher = (char)(((ans[i, 0]) % 26)+97);
                Console.Write("\t" + cipher);

            }

            Console.ReadKey();

        }

    }
}

khi nhập m=2

k:

3

2

3

5

văn bản: help

kết quả đúng: dple

nhưng bài của mình lại ra: dpaa

Mong các bạn fix dùm mình cảm ơn nhiều!

Bình luận

Để bình luận, bạn cần đăng nhập bằng tài khoản Howkteam.

Đăng nhập
Darky đã bình luận 22:54 02-05-2017

https://goo.gl/msJqZL đây là hình ảnh mình debug . 

Mình nhìn code bạn và suy đoán hướng mà bạn đang muốn giải quyết nó . Nên mình cố gắng theo code và sửa nó.

Ở đây mình có cảm giác như là sau khi bạn yêu cầu người dùng nhập vào  m (tức là số hàng = số cột ) tạo thành ma trận vuông và sau đó nếu muốn chương trình chạy được thì chuỗi "text" kiểu string nhập tiếp theo phải bằng với mxm tức bằng với số lượng phần tử trong ma trận . 

Rồi sau giống như bạn đang muốn nhân 2 ma trận lại với nhau vậy , nhưng bị sai ở chỗ là chuỗi bạn yêu cầu người dùng nhập vào và sau đó ToChar thành một mảng gồm các ký tự được tách ra từ chuỗi nhập vào ,nếu như xét là 1 một ma trận thì nó chỉ có 1 dòng và  text.length cột .

           for (i = 0; i < end; i++)
            {
                sum = 0;
                for (j = 0; j < end; j++)
                {
                    sum += mtrx[i, j] * (int)txt[j];
                }
                ans[i, 0] = sum;
            }

 Biến end ở trên bạn cho là end = txt.Length => bằng 4 vì nhập chuỗi là  "help" . Nhưng vòng for thứ 2 nó chạy mảng 2 chiều với m cột m hàng = 2 lúc nhập , vậy khi nó nhảy qua tới end = 2 và end = 3 thì luôn luôn mtrx = 0 .

Mình chỉ fix tạm thời và nó chạy được cách bạn nhập ma trận m=2, m=3 . Do chỉ bạn chỉ để có 1 cách nhập nên mình k test được đúng hay sai . Bạn xem thử có giúp được gì không nhé ! .Nếu chổ nào không hiểu thì cmt nha . Darky :))

        static void Main(string[] args)
        {
            int i, j, end = 0;
            int[,] mtrx = new int[25, 25];
            int[,] ans = new int[25, 1];
            int m;
            string text = "";
            //m
            Console.WriteLine("Nhap m:");
            m = int.Parse(Console.ReadLine());
            //Nhập mã khóa
            Console.WriteLine("Nhap key:");

            for (i = 0; i < m; i++)
            {
                for (j = 0; j < m; j++)
                {
                    Console.Write("Phan tu - [{0}],[{1}]: ", i, j);
                    mtrx[i, j] = int.Parse(Console.ReadLine());
                }
            }
            //Input
            Console.WriteLine("Nhap van ban");
            Console.Write("\n");
            text = Console.ReadLine();
            Console.Write("\n");

            char[] txt = text.ToCharArray();
            end = txt.Length;

            for (i = 0; i < end; i++)
            {
                txt[i] = Convert.ToChar(txt[i] - 'a');
            }
            //Ma trận

            int sum = 0, ViTriBD = 0,ViTriLS = 0 ,PT = 0;
            while (PT < end)
            {
                for (i = 0; i < m; i++)
                {
                    if (ViTriLS != 0)
                    {

                        if (PT % m != 0 && m % 2 == 1) ViTriLS = ViTriBD;
                        else if (PT % m != 0 && m % 2 == 0) ViTriLS = ViTriBD;
                        else
                        {
                            ViTriBD = PT;
                            ViTriLS = ViTriBD;
                        }  
                    }
                    sum = 0;
                    for (j = 0; j < m; j++)
                    {
                        sum += mtrx[i, j] * (int)txt[ViTriLS];
                        ViTriLS++;
                    }
                    ans[PT, 0] = sum; PT++;
                }
            }
            //Output
            Console.Write("Van ban da ma hoa:");

            for (i = 0; i < end; i++)
            {
                char cipher = (char)(((ans[i, 0]) % 26) + 97);
                Console.Write("\t" + cipher);
            }

            Console.ReadKey();
        }

 

Nguyễn Đức Chính đã bình luận 04:40 03-05-2017

Theo định nghĩa mã Hill thì khóa K là một ma trận vuông cấp m và khả nghịch trên modulo 26, hay nói rõ hơn đó là ma trận K phải có ma trận nghịch đảo trên modulo 26. Từ đó suy ra: gcd(det(K), 26) = 1 (Ước chung lớn nhất của định thức K và 26 là 1).

Bạn có thể tham khảo thêm code sau của mình, mình xây dựng dựa trên code của bạn.

Lưu ý là bạn cần phải thêm việc kiểm tra khóa K có hợp lệ hay ko và nếu bản rõ (văn bản cần mã hóa) không phải là bội của m thì bạn xử lý như thế nào?

class Program
    {
        static void Main(string[] args)
        {
            //Ma trận khóa K
            int[,] mtrx;
            //Cấp của ma trận khóa K
            int m;
            //Chuỗi cần mã hóa (Bản rõ)
            char[] plantext;
            //Số hóa bản rõ
            int[] digitizing;
            //Số hóa của bản mã
            int[] cipher;

            //Nhập m và khởi tạo ma trận khóa K
            Console.WriteLine("Nhap m: ");
            m = int.Parse(Console.ReadLine());
            mtrx = new int[m, m];

            //Nhập ma trận khóa K
            Console.WriteLine("Nhap ma tran khoa K:");
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < m; j++)
                {
                    Console.Write("Phan tu ({0}, {1}): ", i, j);
                    mtrx[i, j] = int.Parse(Console.ReadLine());
                }
            }

            //Nhập văn bản cần mã hóa (bản rõ)
            Console.WriteLine("Nhap van ban: ");
            string input = Console.ReadLine();
            plantext = input.ToLower().ToCharArray();

            //Số hóa bản rõ
            digitizing = new int[input.Length];
            cipher = new int[input.Length];
            for (int i = 0; i < input.Length; i++)
            {
                digitizing[i] = (int)plantext[i] - 97;
            }

            //Mã hóa
            for (int i = 0; i < plantext.Length; i += m)
            {
                int[,] a = new int[1, m];
                for (int j = i; j < m + i; j++)
                {
                    a[0, j % m] = digitizing[j];
                }
                NhanMaTran(ref a, mtrx);
                for (int k = i; k < m + i; k++)
                {
                    cipher[k] = a[0, k % m];
                }
            }

            //Nhân ma trận
            void NhanMaTran(ref int[,] a, int[,] b)
            {
                int[,] temp = new int[1, m];
                for (int i = 0; i < m; i++)
                {
                    int sum = 0;
                    for (int j = 0; j < m; j++)
                    {
                        sum += a[0, j] * b[j, i];
                    }
                    temp[0, i] = sum % 26;
                }
                a = temp;
            }

            //In bản mã (số)
            Console.WriteLine();
            Console.Write("Ban ma (so hoa): ");
            for (int i = 0; i < cipher.Length; i++)
            {
                Console.Write(cipher[i] + " ");
            }

            //In bản mã (ký tự)
            Console.WriteLine();
            Console.Write("Ban ma (ky tu): ");
            for (int i = 0; i < cipher.Length; i++)
            {
                Console.Write(((char)(cipher[i] + 97)).ToString().ToUpper() + " ");
            }

            Console.ReadKey();
        }
    }

 

duycongtg2 đã bình luận 19:18 02-05-2017
#include<stdio.h>				
#include<conio.h>
#include<time.h>
#include<Windows.h>
#define max 100
#define modu 26
#define mt 10

void xuatfile(char h[], char file[], int m)
{
	FILE*pFile;
	pFile=fopen(file,"wt"); // File được tạo nằm trong ổ C .
	
	for(int i=0;i<m;i++)
	{
		char ch = h[i];
		fputc(ch, pFile);//Ghi giá trị các phần tử trong mảng vào file .
	}
	fclose(pFile); // Đóng file .
}

int dodai(char file[]) //tìm do dai cua file .
{
	FILE*pFile;
	pFile=fopen(file,"r+t"); // Mở file ra .
	
	int i = 0;
	if(pFile==NULL)
	{
		printf("\nKhong doc duoc File ");
	}
	else
	{

		while(true)
		{
			if(fgetc(pFile) == EOF)
			{
				break;
			
			}
			i++;
		}
	}
	return i;
	fclose(pFile); // Đóng file .
}

void docfile(char e[], char file[], int m)
{
	FILE*pFile;
	pFile=fopen(file,"r+t"); // Mở file ra .
	if(pFile==NULL)
	{
		printf("\nKhong doc duoc File ");
	}
	else
	{
		for(int i = 0; i < m; i++)
		{
			
			char x =fgetc(pFile);// Đọc các giá trị phần tử trong file gán vào x .
			e[i] = x;
			//printf("a[%d]=%c\n", i, e[i]); // Xuất các giá trị ra màn hình .
		}
	}
	e[m] = '\0';
	fclose(pFile); // Đóng file .
}
void xuatmang(int e[], int m)
{
	printf("\nmang la : \n");
	for(int i = 0 ; i < m; i++)
	{
		printf("%4d", e[i]);
	}
}
void chuyensangmangso(char e[], int f[], int m)// chuyen ky tu sang so de xu ly.
{
	for(int i = 0 ; i < m; i++)
	{
		int x = e[i] - 97;
		//printf("%5d", x);
		f[i] = x;
	
	}
}

void mahoa(int a[][mt], int f[],int g[], char h[], int m , int n)
{

	int so = 0;
	for(int i = 0 ; i < m ; i += n)// mã hóa n số một lần .
	{
		
			for(int k = 0 ; k < n; k++) // chạy cột trước .
			{
				int x = 0;
				int y = i;
				
				for(int l = 0; l < n ; l++) // chạy hàng sau .
				{
					x += f[y] * a[l][k];
					//printf("%5d", x);
					y++;

				}
				int z = x;
				//printf("%5d", x);
				x = 0;
				y = i;
				
				g[so] = z % 26;
				//printf("\n %4d %4d", g[so] , so);
				so++;
				
				
				
				
			}
			
	}
	//printf("\nban ma : ");
	for(int i = 0 ; i < m ; i++)
	{
		//printf("%4d",g[i]);
		h[i] = g[i] + 97;

	}
	h[m] = '\0';

}

void giaima(int d[][mt], int f[],int g[], char h[], int m , int n)
{

	int so = 0;
	for(int i = 0 ; i < m ; i += n)// mã hóa n số một lần .
	{
		
			for(int k = 0 ; k < n; k++) // chạy cột trước .
			{
				int x = 0;
				int y = i;
				//int o;
				for(int l = 0; l < n ; l++) // chạy hàng sau .   
				{
					x += f[y] * d[l][k];
					//printf("%5d", x);
					y++;
					//o = l;

				}
				//printf("%5d", o);
				int z = x;
				//printf("\n%5d", x);
				x = 0;
				y = i;
				
				g[so] = z % 26;
				//printf("\n %4d %4d", g[so] , so);
				so++;
							
			}
			
	}
	//printf("\nban ma : ");
	for(int i = 0 ; i < m ; i++)
	{
		//printf("%4d",g[i]);
		h[i] = g[i] + 97;

	}
	h[m] = '\0';

}





void nhap(int a[][mt] , int n)
{
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			printf("nhap phan tu thu a[%d], [%d] : ", i, j);
			scanf_s("%d",&a[i][j]);
		}

	}


}
void taomatran(int a[][mt], int n) // tạo ma trận ngẫu nhiên
{
	srand(time(0));
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			a[i][j] =  rand() % 11; //hàm random
		}

	}


}
void xuat(int a[][mt], int n)
{
	printf("khoa K : \n");
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			printf("%5d", a[i][j]);
		}
		printf("\n");

	}


}

int dinhthuc(int a[][mt], int k) // tính định thức 
{
	int s = 1, det = 0, b[mt][mt];
	int i, j, m, n, c;
	if (k == 1)
	{
		return (a[0][0]);
	}
	else
	{
		det = 0;
		for (c = 0; c < k; c++)
		{
			m = 0;
			n = 0;
			for (i = 0; i < k; i++)
			{
				for (j = 0; j < k; j++)
				{
					b[i][j] = 0;
					if (i != 0 && j != c)
					{
						b[m][n] = a[i][j];
						if (n < (k - 2))
							n++;
						else
						{
							n = 0;
							m++;
						}
					}
				}
			}
			det = det + s * (a[0][c] * dinhthuc(b, k - 1));
			s = -1 * s;
		}
	}

	return (det);
}
int timso(int det) 
{
	int i = 1;
	while (true)
	{
		if ((i * det) % modu == 1)
		{
			return i;
		}
		i++;

	}
	return 0;

}
int timsoam(int det)
{
	int a = det * (-1);
	int i = 1;
	while (true)
	{
		if ((i * a) % modu == 25)
		{
			return i;
		}
		i++;

	}
	return 0;

}
void xoahangcot(int a[][mt], int &n , int dong, int cot)// xoá hang  va cot tương ứng
{
	for(int i = dong; i < n - 1; i++ )
	{
		for (int j = 0; j< n; j++)
		{
			a[i][j] = a[i+1][j];
		}
	}
	for(int i = 0; i < n - 1; i++ )
	{
		for (int j = cot; j< n; j++)
		{
			a[i][j] = a[i][j + 1];
		}
	}
	n--;


}

void matranphu(int a[][mt], int c[][mt], int n)// tạo ma trận phụ
{
	
	
	for(int i = 0 ; i < n; i++)
	{
		for(int j = 0 ; j < n; j++)
		{
			int x = n;
			    int b[mt][mt];
				for(int k = 0 ; k < n; k++)
				{
					for(int l = 0 ; l < n; l++)
					{
			
						 b[k][l] = a[k][l];
						 //printf("%4d", b[k][l]);
						 
			
		
					}
	
				}
				xoahangcot(b, x, j, i);
			  if((i + j) % 2 == 0)
				{
	
					c[i][j] = dinhthuc(b,n-1);
				}
				else
				{
                   c[i][j] = - dinhthuc(b, n -1);
			    }
			

			  //c[i][j] = con(b, x, i, j);
			
		
		}
	
	}
	//printf("\n");
	//xuat(c, n);

}

void matranphuz26(int c[][mt], int d[][mt], int n, int so) // tạo ma trận nghịch đảo trên modu
{
	for(int i = 0; i < n; i++)
	{
		for(int j = 0 ; j < n; j++)
		{
			if(c[i][j] >= 0)
			{
				d[i][j] = (((c[i][j] ) % modu) * so) % modu;
			}
			else
			{
				int x = modu - ((c[i][j] * (-1) ) % modu);
				d[i][j] = (x * so) % modu;

			}
		}
	}
	//printf("\n");
	//xuat(d, n);



}





int main()
{
	int a[mt][mt];
	int n;
	int c[mt][mt];
	int d[mt][mt];
	
	


	char e[max];//a
    int f[max];//b
	int g[max];//c
	char h[max];//d
	int x ;
quaylai:
	printf("-----------------MeNu-----------------");
	printf("\nchon 1 de ma hoa");
	printf("\nchon 2 de giai ma\n");
luachon:
	scanf("%d", &x);
	if(x == 1)
	{
		printf("\nnhap bac ma tran khoa ");
		scanf("%d",&n);
		duycong:
	//system("cls");
		taomatran(a, n);
		//xuat(a, n);
		int det = dinhthuc(a, n);
		
		
		if (det == 0 || det % 2 == 0)
		{
			goto duycong;
		}
		else
		{
			xuat(a, n);
		}
		//printf("\n ............... \n");
	//	int det = dinhthuc(a, n);
		printf("det : %d",det);
		int so ;
		if(det > 0)
		{
			so = timso(det);
		
		}
		else
		{
			so = timsoam(det);
		}
		
		//printf("so : %d", so);
		matranphu(a, c, n);
		matranphuz26(c, d, n, so);
		//printf("\n ............... \n");

		//



		    char filegoc[max];
			printf("\nnhap duong dan va file can ma hoa vidu C://input.txt : ");
			fflush(stdin);
		    gets(filegoc);
			int m = dodai(filegoc);
			printf("%d", m);
			docfile(e, filegoc, m);
			printf("\n");
			//printf("%s", a);
			chuyensangmangso(e, f, m);
			//xuatmang(f, m);
			mahoa(a, f, g, h, m, n);
			//xuatmang(g, m);
			//banma(g, h, m);
			//printf("%s", h);
			char filexuat[max];
			printf("\nnnhap duong dan va ten file can xuat ra C://banma.txt : ");
			fflush(stdin);
			gets(filexuat);
			xuatfile(h, filexuat, m);

	// chay lai ct
				
			printf("\n ban co muon chay lai chuong trinh ko chon y orr Y de chay lai or n N de thoat ");
		int tieptuc;

		fflush(stdin);
		tieptuc = getch();
		
		if(tieptuc=='y'||tieptuc=='Y')
		{
			goto quaylai;
		}
		else
		{
			getch();
			return 0;

		}

	//



	}
	else if(x == 2)
	{

            printf("nhap bac cho ma tran khoa \n");
			scanf("%d", &n);

		    printf("nhap ma tran khoa \n");
			
		    nhap(a, n);
			//
			   int det = dinhthuc(a, n);
			   int so ;
				if(det > 0)
				{
					so = timso(det);
		
				}
				else
				{
					so = timsoam(det);
				}
			   
				//printf("so : %d", so);
				matranphu(a, c, n);
				matranphuz26(c, d, n, so);
			//



		    char filegiai[max];
		    printf("\nnhap duong dan va file can giai ma vidu C://banma.txt : ");
			fflush(stdin);
		    gets(filegiai);
			int m = dodai(filegiai);
			//printf("%d",m);
			docfile(e, filegiai,m);
			chuyensangmangso(e, f, m);
			//xuatmang(f, m);
			giaima(d, f, g, h, m , n);


			//printf("%s", h);
			char filexuat1[max];
			printf("\nnhap duong dan va ten file can xuat ra C://giaima.txt : ");
			fflush(stdin);
			gets(filexuat1);
			xuatfile(h, filexuat1, m);
			fflush(stdin);
	//chay lai ct
			printf(" ban co muon chay lai chuong trinh ko chon y orr Y de chay lai or n N de thoat ");
		int tieptuc;

		fflush(stdin);
		tieptuc = getch();
		
		if(tieptuc=='y'||tieptuc=='Y')
		{
				goto quaylai;
		}
		else
		{
			getch();
			return 0;

		}
	//
	
	}
	else
	{
		printf("\nlua chon ko hop le moi chon lai : ");
		goto luachon;
	}



	//getch();
	//return 0;

}


trước viết = c .bạn thử convert sang c# thử xem

 

K9 SuperAdmin, KquizAdmin, KquizAuthor đã bình luận 17:06 02-05-2017

Mình không rành thuật toán. Nhưng mình có một số kinh nghiệm fix sau.

Bạn có hiểu cái mình viết k. Nếu hiểu thì thử dịch code thành tiếng việt xem code nó nói gì.

Debug tuần tự xem giá trị ra mong muốn đúng như ý k.

Câu hỏi mới nhất