我试图修复我的代码。在我的代码中,我试图生成一个我已经完成的16位密钥。其次,生成随机消息,这也是完成的。加密和解密我收到错误的数据。最后有一个强力算法来解密我稍后尝试做的消息。因此,对于我的加密,代码会对其进行加密,但不会对随机生成的字符串进行加密。我收到了很多错误。
我的代码:
import java.util.Random;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Assignment1Demo {
private static String msg;
private static String msgE;
private static String msgD;
private static int key;
public static void main(String[] args){
//TODO: You can only call methods in main method
key = generateKey();
msg = generateMsg();
msgE = encryption(key,msg);
bruteForce(msgE);
}
private static int generateKey() {
//TODO: implement step a (randomly generate 16-bit key)
//16 bit digit means 2^16 -1 in decimal
Random rand = new Random();
return rand.nextInt((int) (Math.pow(2, 16)-1));
}
private static String generateMsg() {
//TODO: implement step b (randonly generate a string with an even number of characters)
String chractersU="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String chractersL=chractersU.toLowerCase();
String space=" ";
String alphanum=chractersU+space+chractersL;
String random="";
int length=alphanum.length();
Random rand=new Random();
char[] text=new char[length];
for(int i=0;i<length;i++) {
text[i]=alphanum.charAt(rand.nextInt(alphanum.length()));
}
for(int i=0;i<text.length/2;i++) {
if(text.length%2!=0) {
random += text[i];
}}
return random;
}
private static String encryption (int key, String msg) {
//TODO: implement step c (encrypt the message)
String strData="";
String strKey=Integer.toString(key);
try {
SecretKeySpec skeyspec=new SecretKeySpec(strKey.getBytes(),"Blowfish");
Cipher cipher=Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, skeyspec);
byte[] encrypted=cipher.doFinal(msg.getBytes());
strData=new String(encrypted);
} catch (Exception e) {
e.printStackTrace();
}
return strData;
}
private static void decryption(int key, String msgE) {
//TODO: implement step d (decryption)
String strKey = Integer.toString(key);
String strData="";
try {
SecretKeySpec skeyspec=new SecretKeySpec(strKey.getBytes(),"Blowfish");
Cipher cipher=Cipher.getInstance("Blowfish");
cipher.init(Cipher.DECRYPT_MODE, skeyspec);
byte[] decrypted=cipher.doFinal(msgE.getBytes());
strData=new String(decrypted);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(strData);
}
private static void bruteForce(String msgE) {
//TODO: implement bruteForce algorithm, you may need the above decryption(key,msgE) method
boolean isEnglisString = msgE.matches("[a-zA-Z]+");
if(isEnglisString)
System.out.println("Yes encrypted message is Randomly English generated message " + msgE);
else
System.out.println("encrypted message is Not Randomly english generated message "+msgE);
decryption(key, msgE);
isEnglisString = msgD.matches("[a-zA-Z]+");
if(isEnglisString)
System.out.println("Yes decrypted message is Randomly english generated message "+ msgD);
else
System.out.println("decrypted message is not Randomly english generated message "+ msgD);
}}
错误:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:936)
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
at java.base/com.sun.crypto.provider.BlowfishCipher.engineDoFinal(BlowfishCipher.java:319)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2189)
at Assignment1Demo.decryption(Assignment1Demo.java:110)
at Assignment1Demo.bruteForce(Assignment1Demo.java:132)
at Assignment1Demo.main(Assignment1Demo.java:30)
Exception in thread "main" java.lang.NullPointerException
at Assignment1Demo.bruteForce(Assignment1Demo.java:133)
at Assignment1Demo.main(Assignment1Demo.java:30)
答案 0 :(得分:0)
您的字符串是随机生成的,但是当块大小与密码所期望的不匹配时,您需要应用可接受的填充算法,因此输入的大小与算法一致。这适用于所有分组密码。
这个例子是一个简单的密码计,不是一个人可以使用像算法一样的东西 &#34; AES / CBC / PKCS5Padding&#34; &#34; RC2 / CBC / PKCS5Padding&#34; &#34; DESede / CBC / PKCS5Padding (PKCS#5填充定义为8字节块大小)
@Override
public SimpleMeter testEncryption(File baseInput, String algorithm, String provider) throws NoSuchProviderException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
Cipher cipherEncryption;
SimpleMeter meter = new SimpleMeter();
SecureRandom randGenerator = new SecureRandom();
KeyGenerator generator;
generator = KeyGenerator.getInstance(algorithm.split("/")[0], provider);
generator.init(randGenerator);
SecretKey key = generator.generateKey();
cipherEncryption = Cipher.getInstance(algorithm, provider);
cipherEncryption.init(Cipher.ENCRYPT_MODE, key);
try (BufferedInputStream input = new BufferedInputStream(new FileInputStream(baseInput))) {
CipherInputStream encryptionStream = new CipherInputStream(input, cipherEncryption);
meter.start();
while (encryptionStream.read() > -1);
encryptionStream.close();//End all encryption and decryption operation
meter.stop();
} catch (Exception ex) {
ex.printStackTrace();
meter = null;
}
return meter;
}
没有流的另一个例子:
cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decrypted = cipher.doFinal(encryptedString.getBytes(CHARSET_ISO_8859_1));
decryptedString = new String(decrypted, CHARSET_ISO_8859_1);
这真的没有必要,但如果你想使用base64,你可以寻找Apache: http://commons.apache.org/proper/commons-codec/
使用代码的示例
1)ECB模式
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Random;
public class Assignment1Demo {
private static String msg;
private static byte[] msgE;
private static String msgD;
private static int key;
public static void main( String[] args ) {
//TODO: You can only call methods in main method
key = generateKey( );
msg = generateMsg( );
msgE = encryption( key, msg );
bruteForce( msgE );
}
private static int generateKey( ) {
//TODO: implement step a (randomly generate 16-bit key)
//16 bit digit means 2^16 -1 in decimal
Random rand = new Random( );
return rand.nextInt( ( int ) ( Math.pow( 2, 16 ) - 1 ) );
}
private static String generateMsg( ) {
//TODO: implement step b (randonly generate a string with an even number of characters)
String chractersU = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String chractersL = chractersU.toLowerCase( );
String space = " ";
String alphanum = chractersU + space + chractersL;
String random = "";
int length = alphanum.length( );
Random rand = new Random( );
char[] text = new char[ length ];
for ( int i = 0; i < length; i++ ) {
text[ i ] = alphanum.charAt( rand.nextInt( alphanum.length( ) ) );
}
for ( int i = 0; i < text.length / 2; i++ ) {
if ( text.length % 2 != 0 ) {
random += text[ i ];
}
}
return random;
}
private static byte[] encryption( int key, String msg ) {
//TODO: implement step c (encrypt the message)
byte[] encrypted =new byte[]{};
String strKey = Integer.toString( key );
try {
SecretKeySpec skeyspec = new SecretKeySpec( strKey.getBytes( ), "Blowfish" );
Cipher cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
cipher.init( Cipher.ENCRYPT_MODE, skeyspec );
encrypted = cipher.doFinal( msg.getBytes( ) );
}
catch ( Exception e ) {
e.printStackTrace( );
}
return encrypted;
}
private static void bruteForce( byte[] msgE ) {
//TODO: implement bruteForce algorithm, you may need the above decryption(key,msgE) method
decryption( key, msgE );
}
private static void decryption( int key, byte[] msgE ) {
//TODO: implement step d (decryption)
String strKey = Integer.toString( key );
String strData = "";
try {
SecretKeySpec skeyspec = new SecretKeySpec( strKey.getBytes( ), "Blowfish" );
Cipher cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
cipher.init( Cipher.DECRYPT_MODE, skeyspec );
byte[] decrypted = cipher.doFinal( msgE);
strData = new String( decrypted );
}
catch ( Exception e ) {
e.printStackTrace( );
}
System.out.println( strData );
}
}
示例2)您的CBC模式代码
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.util.Random;
public class Assignment1Demo {
private static String msg;
private static byte[] msgE;
private static String msgD;
private static int key;
private static byte[] encodedParams;
public static void main( String[] args ) {
//TODO: You can only call methods in main method
key = generateKey( );
msg = generateMsg( );
msgE = encryption( key, msg );
bruteForce( msgE );
}
private static int generateKey( ) {
//TODO: implement step a (randomly generate 16-bit key)
//16 bit digit means 2^16 -1 in decimal
Random rand = new Random( );
return rand.nextInt( ( int ) ( Math.pow( 2, 16 ) - 1 ) );
}
private static String generateMsg( ) {
//TODO: implement step b (randonly generate a string with an even number of characters)
String chractersU = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String chractersL = chractersU.toLowerCase( );
String space = " ";
String alphanum = chractersU + space + chractersL;
String random = "";
int length = alphanum.length( );
Random rand = new Random( );
char[] text = new char[ length ];
for ( int i = 0; i < length; i++ ) {
text[ i ] = alphanum.charAt( rand.nextInt( alphanum.length( ) ) );
}
for ( int i = 0; i < text.length / 2; i++ ) {
if ( text.length % 2 != 0 ) {
random += text[ i ];
}
}
return random;
}
private static byte[] encryption( int key, String msg ) {
//TODO: implement step c (encrypt the message)
byte[] encrypted =new byte[]{};
String strKey = Integer.toString( key );
try {
SecretKeySpec skeyspec = new SecretKeySpec( strKey.getBytes( ), "Blowfish" );
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
cipher.init( Cipher.ENCRYPT_MODE, skeyspec );
encrypted = cipher.doFinal( msg.getBytes( ) );
encodedParams = cipher.getParameters().getEncoded();
}
catch ( Exception e ) {
e.printStackTrace( );
}
return encrypted;
}
private static void bruteForce( byte[] msgE ) {
//TODO: implement bruteForce algorithm, you may need the above decryption(key,msgE) method
decryption( key, msgE );
}
private static void decryption( int key, byte[] msgE ) {
//TODO: implement step d (decryption)
String strKey = Integer.toString( key );
String strData = "";
try {
SecretKeySpec skeyspec = new SecretKeySpec( strKey.getBytes( ), "Blowfish" );
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
AlgorithmParameters params = AlgorithmParameters.getInstance("Blowfish");
params.init(encodedParams);
cipher.init( Cipher.DECRYPT_MODE, skeyspec, params );
byte[] decrypted = cipher.doFinal( msgE);
strData = new String( decrypted );
}
catch ( Exception e ) {
e.printStackTrace( );
}
System.out.println( strData );
}
}
答案 1 :(得分:0)
简而言之,您使用的是加密的二进制数据并假设它是有效的文本,一般来说它不会是。
您可以使用UTF-8编码将String编码为byte [],但并非所有可能的byte []编码都是有效的字符串。加密数据时,可以使用任何可能的字节,但不能总是使用标准字符编码将其转换为字符串。这可能导致数据长度发生变化,这就是为什么它不再是数据编码时的8的倍数。
将数据编码为可打印字符串的简单方法是使用Base64编码。
在encryption
中使用
strData = DatatypeConverter.printBase64Binary(encrypted);
并在decryption
中使用
byte[] decrypted=cipher.doFinal(DatatypeConverter.parseBase64Binary(msgE));
这样您将始终尝试解密您编写的二进制数据。
另一个选择是不尝试将二进制数据存储在String中,只使用原始byte[]
编辑可以使用byte[]
代替String
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
public class A {
public static void main(String... args) {
String text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < text.length(); i++) {
byte[] encrypt = encryption(1, text.substring(0, i));
String hello = decryption(1, encrypt);
System.out.println(hello);
}
}
private static byte[] encryption(int key, String msg) {
String strKey = Integer.toString(key);
try {
SecretKeySpec skeyspec = new SecretKeySpec(strKey.getBytes(), "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, skeyspec);
return cipher.doFinal(msg.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static String decryption(int key, byte[] msgE) {
String strKey = Integer.toString(key);
try {
SecretKeySpec skeyspec = new SecretKeySpec(strKey.getBytes(), "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.DECRYPT_MODE, skeyspec);
byte[] decrypted = cipher.doFinal(msgE);
return new String(decrypted, StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}