Decrypting Mapping Cipher

本文介绍了一种基于字母映射表的密文解密算法实现。通过输入特定的字母映射密文及加密后的句子,算法能够准确地将密文还原为明文。示例展示了如何使用该算法进行解密操作。

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

题目: 先输入字母映射的密文, 再将输入的加密后的句子中的字母, 得其所对应密文中相同字母的位置, 将其位置的位数所对应字母表中的字母输出。(解密)

    Decrypting Mapping Cipher
Recall the Mapping Cipher laboratory work. You are given an alphabetic mapping
table to create cipher text. The table is defined by a string using 26 lower-case
alphabets, such as
incpfvztsmbexowhlgkqjyrdau
In the string all characters are different. Using this table to generate cipher text, it
performs the following mapping scheme:
a -> i, A->I
b -> n, B->N
c -> c, C->C
d -> p, D->P
. . . . . . .
y -> a, Y->A
z -> u, Z->U
Any non-alphabetic character are kept unchanged.
Apply the scheme to plain text:
There are 2 dogs and 3 cats.
It rains dogs & cats!
Obtain the following cipher text:
Qtfgf igf 2 pwzk iop 3 ciqk.
Sq gisok pwzk & ciqk!
Now, you are asked to do its inverse task. You are given the same mapping string, but
you will receive cipher text. Your mission is to decrypt the cipher text to a plain one.

Input
There are several test cases. Each test case starts with a line of mapping string used to
create cipher text. Following are cipher text enclosed by two lines of string "***".
Your task is to output the plain text before encryption. There is a blank line after each
case. Finally, you will reach a line of string "###" which signals the end of test.
Each line in test cases is no more than 1000 characters.

Output
The cipher text of each test case is prefixed with a plain text number as shown in the
sample output. Place a blank line between cases.

Sample Input
incpfvztsmbexowhlgkqjyrdau
***
Qtfgf igf 2 pwzk iop 3 ciqk.
Sq gisok pwzk & ciqk!
***
xowhlgkqjyrdauincpfvztsmbe
***
Vqlpl xpl 2 hikf xuh 3 wxvf.
Jv pxjuf hikf & wxvf!
***
###

Sample Output
Plain 1:
There are 2 dogs and 3 cats.
It rains dogs & cats!
Plain 2:
There are 2 dogs and 3 cats.
It rains dogs & cats!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	int flag=1, test=1;
	
	while(1)
	{
		char arr[26]={0}; //存取字母映射的密文
		char z[10]={0}; //存取密文后的***
		char str[1001]={0}; //存取输入的加密后的句子
		
		gets(arr);
		if(arr[0]=='#' && arr[1]=='#' && arr[2]=='#') break;
		
		gets(z);
		
		if(flag) flag=0;
		else printf("\n");
		
		printf("Plain %d:\n",test++);
		
		while(gets(str))
		{
			if(str[0]=='*' && str[1]=='*' && str[2]=='*') break;
			
			for(int i=0; i<strlen(str); i++)
			{
				if(str[i]>='a' && str[i]<='z' || str[i]>='A' && str[i]<='Z')
				{
					for(int j=0; j<26; j++)
					{
						if(str[i]==arr[j])
						{
							printf("%c",j+'a');
							break;
						}
						
						else if(str[i]+'a'-'A'==arr[j])
						{
							printf("%c",j+'A');
							break;
						}	
					}
				}
				
				else printf("%c",str[i]);
			}
			
			printf("\n");
		}
		
		scanf("\n");
			
	}
    
    return 0;
}



资源下载链接为: https://pan.quark.cn/s/f989b9092fc5 今天给大家分享一个关于C#自定义字符串替换方法的实例,希望能对大家有所帮助。具体介绍如下: 之前我遇到了一个算法题,题目要求将一个字符串中的某些片段替换为指定的新字符串片段。例如,对于源字符串“abcdeabcdfbcdefg”,需要将其中的“cde”替换为“12345”,最终得到的结果字符串是“ab12345abcdfb12345fg”,即从“abcdeabcdfbcdefg”变为“ab12345abcdfb12345fg”。 经过分析,我发现不能直接使用C#自带的string.Replace方法来实现这个功能。于是,我决定自定义一个方法来完成这个任务。这个方法的参数包括:原始字符串originalString、需要被替换的字符串片段strToBeReplaced以及用于替换的新字符串片段newString。 在实现过程中,我首先遍历原始字符串,查找需要被替换的字符串片段strToBeReplaced出现的位置。找到后,就将其替换为新字符串片段newString。需要注意的是,在替换过程中,要确保替换操作不会影响后续的查找和替换,避免遗漏或重复替换的情况发生。 以下是实现代码的大概逻辑: 初始化一个空的字符串result,用于存储最终替换后的结果。 使用IndexOf方法在原始字符串中查找strToBeReplaced的位置。 如果找到了,就将originalString中从开头到strToBeReplaced出现位置之前的部分,以及newString拼接到result中,然后将originalString的查找范围更新为strToBeReplaced之后的部分。 如果没有找到,就直接将剩余的originalString拼接到result中。 重复上述步骤,直到originalStr
### 关于 `IllegalBlockSizeException` 的解决方案 当遇到 `javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher` 错误时,通常是因为加密算法(如 DES 或 AES)要求输入数据的长度必须满足特定条件。以下是可能的原因及其对应的解决方案: #### 原因分析 1. **输入数据未对齐到块大小** 加密算法(如 DES 和 AES)通常是基于固定块大小操作的。对于 DES 来说,其块大小为 8 字节。如果输入的数据长度不是 8 的倍数,则会抛出此异常[^1]。 2. **填充模式配置错误** 如果使用的填充模式(如 PKCS5Padding 或 NoPadding)与实际处理方式不符,也可能引发该问题。例如,在解密过程中期望的是带填充的内容,而实际上接收到的是无填充的内容[^4]。 3. **密钥或初始化向量 (IV) 配置不当** 密钥或 IV 不匹配可能导致解密失败,并触发类似的异常。特别是当使用 CBC 模式时,IV 是必需的参数之一[^5]。 --- #### 解决方案 ##### 方案一:调整输入数据长度 确保待解密的数据长度是对齐到指定块大小的整数倍。可以通过以下方法实现: - 使用合适的填充机制来扩展原始消息至所需长度。 - 在编码阶段显式设置填充策略,比如采用标准库中的 `Cipher.getInstance("DES/CBC/PKCS5Padding")`[^1]。 ##### 方案二:验证并修正填充选项 确认所选密码实例是否支持当前应用需求下的填充类型。例如切换成不依赖额外字节补充的方式——即 `"NoPadding"` 可能适合某些场景下无需考虑边界情况的应用程序设计: ```java Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); ``` > 注意:选择不同的 padding scheme 将影响最终输出形式以及兼容性,请谨慎决定具体实施方案! ##### 方案三:检查密钥有效性及一致性 务必保证两端通信双方共享完全一致的秘密信息作为加解密依据。任何细微差异都足以破坏整个流程正常运作[^3]: ```java // 正确生成符合规格定义的标准密钥对象样本代码片段展示如下所示: SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes,"AES"); // 这里假设 keyBytes 已经被正确定义好 cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); ``` 另外值得注意的一点在于部分情况下还涉及到随机数种子序列化等问题也需要同步加以关注处理才行哦~ --- ### 示例代码 下面提供了一个简单的 Java 实现示例,演示如何正确地进行 AES 加密和解密以避免此类问题的发生: ```java import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.security.SecureRandom; public class AESEncryptionExample { private static final String ALGORITHM = "AES"; private static final int KEY_SIZE = 128; public byte[] encrypt(byte[] plaintext, SecretKey key) throws Exception{ Cipher cipher=Cipher.getInstance(ALGORITHM+"/CBC/PKCS5PADDING"); IvParameterSpec ivspec=new IvParameterSpec(new byte[cipher.getBlockSize()]); cipher.init(Cipher.ENCRYPT_MODE,key,ivspec,new SecureRandom()); return cipher.doFinal(plaintext); } public byte[]decrypt(byte[] ciphertext ,SecretKey key)throws Exception{ Cipher cipher=Cipher.getInstance(ALGORITHM+"/CBC/PKCS5PADDING"); IvParameterSpec ivspec=new IvParameterSpec(new byte[cipher.getBlockSize()]); cipher.init(Cipher.DECRYPT_MODE,key,ivspec); return cipher.doFinal(ciphertext ); } public static void main(String args[])throws Exception{ KeyGenerator kg=KeyGenerator.getInstance(ALGORITHM); kg.init(KEY_SIZE); SecretKey sk=kg.generateKey(); AESEncryptionExample example=new AESEncryptionExample(); String message="This is a test."; System.out.println("Original Message:"+message); byte[] encryptedText=example.encrypt(message.getBytes(),sk); System.out.println("Encrypted Text(Hex):"+bytesToHex(encryptedText)); byte[] decryptedText=example.decrypt(encryptedText,sk); System.out.println("Decrypted Text:" +new String(decryptedText)); } private static String bytesToHex(byte[] hash){ StringBuilder hexString=new StringBuilder(2*hash.length); for(int i=0;i<hash.length;i++){ String hex=Integer.toHexString(0xff & hash[i]); if(hex.length()==1){ hex='0'+hex; } hexString.append(hex); } return hexString.toString().toUpperCase(); } } ``` --- ### 总结 通过以上讨论可以看出,“input length must be multiple of X” 类型的问题主要是由于未能遵循目标加密技术的要求所致。因此建议开发者们仔细阅读官方文档了解各种 API 参数含义的同时也要注意实践过程中的细节把控工作这样才能有效减少类似 bug 出现几率从而提升软件质量水平。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值