#java #aes #encryption
#java #aes #шифрование
Вопрос:
Я мало что знал о шифровании / дешифровании Java, так как мое требование простое, зашифруйте одну строку текста в шестнадцатеричную строку (чтобы ее можно было поместить в URL-адрес браузера), я копирую приведенный ниже код из Интернета, он работает, но только в Windows (XP / 7), наMac расшифрованная строка — это полный беспорядок, не могли бы вы помочь мне выяснить, где что-то не так?
public static String encrypt( String content, String password ) throws NoSuchAlgorithmException,
NoSuchPaddingException, UnsupportedEncodingException, InvalidKeyException, IllegalBlockSizeException,
BadPaddingException
{
KeyGenerator kgen = KeyGenerator.getInstance( "AES" );
kgen.init( 128, new SecureRandom( password.getBytes() ) );
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec( enCodeFormat, "AES" );
Cipher cipher = Cipher.getInstance( "AES" );
byte[] byteContent = content.getBytes( "utf-8" );
cipher.init( Cipher.ENCRYPT_MODE, key );
byte[] result = cipher.doFinal( byteContent );
return parseByte2HexStr( result );
}
public static String decrypt( String contents, String password ) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
byte[] content = parseHexStr2Byte( contents );
KeyGenerator kgen = KeyGenerator.getInstance( "AES" );
kgen.init( 128, new SecureRandom( password.getBytes() ) );
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec( enCodeFormat, "AES" );
Cipher cipher = Cipher.getInstance( "AES" );
cipher.init( Cipher.DECRYPT_MODE, key );
byte[] result = cipher.doFinal( content );
return new String( result );
}
public static String parseByte2HexStr( byte buf[] )
{
StringBuffer sb = new StringBuffer();
for( int i = 0; i < buf.length; i )
{
String hex = Integer.toHexString( buf[i] amp; 0xFF );
if( hex.length() == 1 )
{
hex = '0' hex;
}
sb.append( hex.toUpperCase() );
}
return sb.toString();
}
public static byte[] parseHexStr2Byte( String hexStr )
{
if( hexStr.length() < 1 )
return null;
byte[] result = new byte[ hexStr.length() / 2 ];
for( int i = 0; i < hexStr.length() / 2; i )
{
int high = Integer.parseInt( hexStr.substring( i * 2, i * 2 1 ), 16 );
int low = Integer.parseInt( hexStr.substring( i * 2 1, i * 2 2 ), 16 );
result[i] = ( byte ) ( high * 16 low );
}
return resu<
}
Комментарии:
1. Реализации SecureRandom отличаются
Ответ №1:
Не копируйте код из «Интернета», так как там много дерьма, как вы выясняете на собственном горьком опыте. В этом коде есть как минимум 2 существенных ошибки.
- Ошибочно предполагается, что если вы предоставляете SecureRandom начальное значение, это начальное значение является единственными данными, используемыми для заполнения экземпляра SecureRandom.
- Использует кодировку по умолчанию в методе String.getBytes(). Почти всегда вы должны явно указать кодировку UTF-8 для использования шифрования.
В вашем случае # 1, вероятно, проблема, # 2, вероятно, не причиняет вам вреда.
Правильное решение — использовать правильный алгоритм шифрования на основе пароля (PBE). К сожалению, поставщики Sun не поддерживают какие-либо алгоритмы PBE на основе AES. Если вы добавите в свой проект поставщика bouncycastle, вы сможете получить алгоритмы PBE на основе AES.