1031 - Insecure in Prague

本文介绍了一种名为Kant-DeWitt的加密方案,并提供了一个破解该加密方案的算法实现。该方案通过重复消息并填充随机字符来增加解密难度。文章详细解释了加密过程,并给出了一个用于确定最长可能被编码消息的算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Prague is a dangerous city for developers of cryptographic schemes. In 2001, a pair of researchers in Prague announced a security flaw in the famous PGP encryption protocol. In Prague in 2003 , a flaw was discovered in the SSL/TLS (Secure Sockets Layer and Transport Layer Security) protocols. However, Prague's reputation for being tough on cryptographic protocols hasn't stopped the part-time amateur cryptographer and full-time nutcase, Immanuel Kant-DeWitt (known to his friends as "I. Kant-DeWitt"), from bringing his latest encryption scheme to Prague. Here's how it works:

A plain text message p of length n is to be transmitted. The sender chooses an integer m$ \ge$2n, and integerssti, and j, where 0$ \le$stij < m and i < j. The scheme works as follows: m is the length of the transmitted ciphertext string, c. Initially, c contains m empty slots. The first letter of p is placed in position s of c. The k-th letter, k$ \ge$2, is placed by skipping over i empty slots in c after the (k - 1)-st letter, wrapping around to the beginning of c if necessary. Slots already containing letters are not counted as empty. For instance, if the message is PRAGUE, if s = 1i = 6, and m = 15, then the letters are placed in c as follows:

AP U    RG  E --

Starting with the first empty slot in or after position t in string c, the plain text message is entered again, but this time skipping j empty slots between letters. For instance, if t = 0 and j = 8, the second copy of p is entered as follows (beginning in position 2, the first empty slot starting from t = 0):

APPUR AURGEGE --

Finally, any remaining unfilled slots in c are filled in with randomly chosen letters:

APPURAAURGEGEWE --

Kant-DeWitt believes that the duplication of the message, combined with the use of random letters, will confuse decryption schemes based upon letter frequencies and that, without knowledge of s and i, no one can figure out what the original message is. Your job is to try to prove him wrong. Given a number of ciphertext strings (and no additional information), you will determine the longest possible message that could have been encoded using the Kant-DeWitt method.

Input 

A number of ciphertext strings, one per line. Each string will consist only of upper case alphabetic letters, with no leading or trailing blanks; each will have length between 2 and 40.

Input for the last test case is followed by a line consisting of the letter X.

Output 

For each input ciphertext string, print the longest string that could be encrypted in the ciphertext. If more than one string has the longest length, then print `Codeword not unique'. Follow the format of the sample output given below.

Sample Input 

APPURAAURGEGEWE
ABABABAB
THEACMPROGRAMMINGCONTEST
X

Sample Output 

Code 1: PRAGUE
Code 2: Codeword not unique
Code 3: Codeword not unique


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char a[41],count[26],current[21],mark[41],remain[81],ans[21],pos[41][41][41];
int i,j,k,n,go,len,step,skips,maxl,remains,start,unique,cases,ok;
int main()
{
	for(len=1;len<41;len++)
		for(step=1;step<41;step++)
		{
			memset(mark,0,sizeof(mark));
			go=0;
			mark[0]=1;
			pos[len][step][0]=0;
			for(i=1;i<len;i++)
			{
				skips=(step-1)%(len-i)+1;
				while(skips)
				{
					go++;
					if(go>=len)
						go=0;
					if(!mark[go])
						skips--;
				}
				mark[go]=1;
				pos[len][step][i]=go;
			}
		}
	while(1)
	{
		gets(a);
		for(n=0;a[n];n++);
			if(n<2)
				break;
		cases++;
		maxl=0;
		unique=0;
		memset(ans,0,sizeof(ans));
		memset(count,0,sizeof(count));
		for(i=0;i<n;i++)
			count[a[i]-'A']++;
		for(i=0;i<n;i++)
			if(count[a[i]-'A']>1)
				for(j=1;j<n;j++)
				{
					memset(current,0,sizeof(current));
					memset(mark,0,sizeof(mark));
					go=i;
					for(len=0;len<n/2;len++)
					{
						current[len]=a[go];
						mark[go]=1;
						if(len>=maxl&&strcmp(current,ans))
						{
							
							remains=0;
							ok=0;
							for(k=0;k<n;k++)
								if(!mark[k])
									remain[remains++]=a[k];
							for(k=0;k<remains;k++)
								remain[remains+k]=remain[k];
							for(start=0;start<remains;start++)
								if(remain[start]==current[0])
								{
									for(step=j+1;step<=n;step++)
									{
										for(k=1;k<=len;k++)
											if(remain[pos[remains][step][k]+start]!=current[k])
												break;
										if(k>len)
										{
											ok=1;
											
											if(len>maxl)
											{
												maxl=len;
												unique=1;
												memcpy(ans,current,sizeof(current));
											}
											else if(unique)
											{
												maxl++;
												unique=0;
											}
											else
											{
												unique=1;
												memcpy(ans,current,sizeof(current));
											}
											break;
										}
									}
									if(ok)
										break;
								}
						}
						skips=j;
						while(skips)
						{
							go++;
							if(go>=n)
								go=0;
							if(!mark[go])
								skips--;
						}
					}
				}
				printf("Code %d: ",cases);
				puts(unique?ans:"Codeword not unique");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值