草庐IT

维吉尼亚密码

.98℃ 2023-04-03 原文

维吉尼亚密码(又译维热纳尔密码)是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。

【加密原理】

明文:I Love You

密钥:OK

        首先,密钥长度需要与明文长度相同,如果少于明文长度,则重复拼接直到长度相等。本例中,明文长度为8个字母(非字母忽略),密钥补全为“OKOKOKOK”。

      然后根据密码表进行加密。明文第一个字母是“I”,密钥第一个字母是“O”,在表格中找到“I”列与“O”行的相交点,字母“W”就是密文的第一个字母。同理,“L”列与“K”行交点字母是“V”。“O”列与“O”行交点字母是“C”……以此类推,得到密文: W VCFS ICE。     

【解密原理】

密文:PWZRNZBZ EA NQKBUHN LNB

密钥:wind

        首先把密钥重复拼接到和密文长度相同,上例中密文为20位字母,密钥拼接后为:windwindwindwindwind。

        密文P对应密钥W,在密码表中找出W行为P的列,沿着这一列向上找到最上面的字母是T。以此类推,得到明文:tomorrow is another day。

【卡西斯基试验】是基于类似的常用单词有可能被同样的密钥字母进行加密,从而在密文中重复出现。例如,明文中不同的CRYPTO可能被密钥ABCDEF加密成不同的密文:

密钥:ABCDEF   AB  CDEFA   BCD   EFABCDEFABCD

明文:CRYPTO  IS    SHORT   FOR  CRYPTOGRAPHY

密文:CSASXT   IT    UKSWT  GQU  GWYQVRKWAQJB

此时明文中重复的元素在密文中并不重复。然而,如果密钥相同的话,结果可能便为(使用密钥ABCD):

密钥:ABCDAB  CD  ABCDA   BCD   ABCDABCDABCD

明文:CRYPTO  IS   SHORT   FOR   CRYPTOGRAPHY

密文:CSASTP  KV  SIQUT    GQU   CSASTPIUAQJB

此时卡西斯基试验就能产生效果。对于更长的段落此方法更为有效,因为通常密文中重复的片段会更多。如通过下面的密文就能破译出密钥的长度:

密文:DYDUXRMHTVDVNQDQNWDYDUXRMHARTJGWNQD

其中,两个DYDUXRMH的出现相隔了18个字母。因此,可以假定密钥的长度是18的约数,即长度为18、9、6、3或2。而两个NQD则相距20个字母,意味着密钥长度应为20的约数,20、10、5、4或2。取两者的交集,则可以基本确定密钥长度为2。

一旦能够确定密钥的长度,密文就能重新写成多列,列数与密钥长度对应。这样每一列其实就是一个凯撒密码,而此密码的密钥(偏移量)则对应于维吉尼亚密码密钥的相应字母。与破译凯撒密码类似的方法,就能将密文破译。

【C++实现】

#include<iostream> 
using namespace std;
#define MINCHAR 32 
#define CHARSUM 94 
char table[CHARSUM][CHARSUM];
bool Init();
bool Encode(char* key, char* source, char* dest);
bool Dncode(char* key, char* source, char* dest);
int main()
{
	if (!Init())
	{
		cout << "初始化错误!" << endl;
		return 1;
	}
	char key[256];
	char str1[256];
	char str2[256];
	int operation;
	while (1)
	{
		do
		{
			cout << "请选择一个操作:1. 加密; 2. 解密; -1. 退出\n";
			cin >> operation;
		} while (operation != -1 && operation != 1 && operation != 2);
		if (operation == -1)
			return 0;
		else if (operation == 1)//加密 
		{
			cout << "请输入密钥:";
			cin >> key;
			cout << "请输入待加密字符串:";
			cin >> str1;
			Encode(key, str1, str2);
			cout << "加密后的字符串:" << str2 << endl;
		}
		else if (operation == 2)//解密 
		{
			cout << "请输入密钥:";
			cin >> key;
			cout << "请输入待解密字符串:";
			cin >> str1;
			Dncode(key, str1, str2);
			cout << "解密后的字符串:" << str2 << endl;
		}
		cout << endl;
	}
	return 0;
}
// 初始化维吉尼亚方阵 
bool Init()
{
	int i, j;
	for (i = 0; i < CHARSUM; i++)
	{
		for (j = 0; j < CHARSUM; j++)
		{
			table[i][j] = MINCHAR + (i + j) % CHARSUM;
		}
	}
	return true;
}
// 加密 
// key:密钥 
// source:待加密的字符串 
// dest:经过加密后的字符串 
bool Encode(char* key, char* source, char* dest)
{
	char* tempSource = source;
	char* tempKey = key;
	char* tempDest = dest;
	do
	{
		*tempDest = table[(*tempKey) - MINCHAR][(*tempSource) - MINCHAR];
		tempDest++;
		if (!(*(++tempKey)))
			tempKey = key;
	} while (*tempSource++);
	dest[strlen(source)] = 0;
	return true;
}
// 解密 
// key:密钥 
// source:待解密的字符串 
// dest:经过解密后的字符串 
bool Dncode(char* key, char* source, char* dest)
{
	char* tempSource = source;
	char* tempKey = key;
	char* tempDest = dest;
	char offset;
	do
	{
		offset = (*tempSource) - (*tempKey);
		offset = offset >= 0 ? offset : offset + CHARSUM;
		*tempDest = MINCHAR + offset;
		tempDest++;
		if (!(*(++tempKey)))
			tempKey = key;
	} while (*++tempSource);
	dest[strlen(source)] = 0;
	return true;
}

有关维吉尼亚密码的更多相关文章

  1. ruby-on-rails - 在 Rails 中自定义 "Password confirmation doesn' t 匹配密码 - 2

    有没有办法在Rails中为确认字段自定义消息?例如在设计中我必须输入密码和password_confirmation并且错误消息是:Passwordconfirmationdoesn'tmatchPassword我可以更改事件记录语言环境消息(“不匹配”),但它会在该语言环境消息的开头和结尾输出密码确认和密码,所以我得到如下内容:"PasswordconfirmationmustmatchPassword"有没有办法将其更改为不同的字符串?PasswordconfirmationandPasswordmustmatch.编辑另一件事是拥有完全自定义的消息,例如:'Setpassword

  2. ruby-on-rails - 我如何比较 'Bcrypt' Gem解密的密码和加密的密码 - 2

    我正在尝试对某些帖子的评论使用简单的身份验证。用户使用即时ID和密码输入评论我使用“bcrypt”gem将密码存储在数据库中。在comments_controller.rb中像这样@comment=Comment.new(comment_params)bcrypted_pwd=BCrypt::Password.create(@comment.user_pwd)@comment.user_pwd=bcrypted_pwd当用户想要删除他们的评论时,我使用data-confirm-modalgem来确认数据在这部分,我必须解密用户输入的密码以与数据库中的加密密码进行比较我怎样才能解密密码,

  3. ruby-on-rails - 如何在记录更新期间从验证中排除密码字段? ( rails 3.0.4, ruby 1.9.2) - 2

    我有一个允许更新用户记录的表单。它包含:password和:password_confirmation字段,但我不希望在数据库中已存储加密密码时对它们运行验证。View文件中的字段:'ConfirmPassword'%>在互联网上搜索时,我发现了这段代码,我认为它是针对以前版本的Ruby/Rails的。(我会把它放在我的用户模型中。)validates_presence_of:password,:on=>create由于我的用户模型中密码验证的语法不同(如下),我对我需要的语法感到困惑。validates:password,:presence=>true,:confirmation=>

  4. ruby-on-rails - Devise 在更改密码后注销用户 - 2

    我正在使用devise,当用户更改密码时,网站会将他们注销。我在网上读到,添加sign_in可以解决问题但不起作用,并且当密码更改时用户会注销。这是我的代码if@user.errors[:base].empty?and@user.update_attributes(params[:user])sign_in(current_user,:bypass=>true)flash[:success]="Useraccounthasbeensuccessfullyupdated"redirect_toedit_user_path(params[:site_id],@user)elserender

  5. ruby - 存储外部 API 的密码 - 最佳实践 - 2

    如果我构建了一个应用程序来访问来自Gmail、Twitter和Facebook的一些数据,并且我希望用户只需输入一次他们的身份验证信息,并且在几天或几周后重置,那会怎样是在Ruby中动态执行此操作的最佳方法吗?我看到很多人只是拥有他们客户/用户凭证的配置文件,如下所示:gmail_account:username:myClientpassword:myClientsPassword这看起来a)非常不安全,b)如果我想为成千上万的用户存储此类信息,它就无法工作。推荐的方法是什么?我希望能够在这些服务之上构建一个界面,因此每次用户进行交易时都必须输入凭据是不可行的。

  6. ruby-on-rails - 最灵活的 Rails 密码安全实现 - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭8年前。Improvethisquestion我需要实现具有各种灵活需求的密码安全。这些要求基本上取自Sanspasswordpolicy:Strongpasswordshavethefollowingcharacteristics:Containatleastthreeofthe

  7. ruby - Net::SSH sudo 命令在输入密码后挂起 - 2

    我一直在尝试使用Thor编写一个小型库,以帮助我快速创建新项目和站点。我写了这个小方法:defssh(cmd)Net::SSH.start(server_ip,user,:port=>port)do|session|session.execcmdendend只是协助我在需要时在远程服务器上运行快速命令。问题是当我需要在远程端的sudo下运行命令时,脚本似乎卡在我身上。例如当执行这个...ssh("sudocp#{file_from_path}#{file_to_path}")脚本会提示我输入密码[sudo]passwordforuser:但是在输入之后整个事情就挂起。有人会碰巧知道它为

  8. ruby - 如何在没有用户名和密码的情况下访问代理? - 2

    我想使用nokogiri和mechanize自动化一个计时网络客户端。我需要通过代理服务器连接,但问题是,我不知道所述代理服务器的用户名和密码。我想获取存储在计算机上的此代理的缓存凭据..例如,在c#中你可以使用:stringproxyUri=proxy.GetProxy(requests.RequestUri).ToString();requests.UseDefaultCredentials=true;requests.Proxy=newWebProxy(proxyUri,false);requests.Proxy.Credentials=System.Net.Credential

  9. ruby-on-rails - 在 Ruby on Rails 中验证 Django 密码给出不匹配的密码 - 2

    我正在用RubyonRails重写Django应用程序,并希望为用户保留旧密码。Django使用PBKDF2SHA1作为加密机制。所以我有一个加密密码是这个pbkdf2_sha256$10000$YsnGfP4rZ1IZ$Tpf4922MoNEjuJQA9EG2Elptyt3dMAyzBPUgmunFOW4=原密码是2bulls在Ruby中,我使用PBKDF256gem和base64进行检查。Base64.encode64PBKDF256.dk("2bulls","YsnGfP4rZ1IZ",10000,32)我很期待Tpf4922MoNEjuJQA9EG2Elptyt3dMAyzBP

  10. ruby - 为什么 rvm install 2.0.0 要求输入 sudo 密码? - 2

    我正在尝试通过rvm安装ruby​​2.0.0-p247。但是,它要求输入密码。提供sudo密码正常吗?我没有在sudoers文件中配置sudo密码。我正在使用OracleEnterpriseLinux6x64。 最佳答案 sudo用于autolibs-这意味着RVM将安装所需的软件,如openssh或libyaml,这是标准ruby​​正常工作所必需的。您可以更改autolibs以查看所需的包而不是安装它们:rvmautolibsread-fail并恢复到安装要求的默认设置:rvmautolibsreset

随机推荐