вторник, 29 июня 2010 г.

Освоение криптографии - 1: алгоритм DES

До сих пор как-то не приходилось серьёзно знакомиться с шифрованием данных. Https защищал мои приложения не только от хакеров, но и от необходимости о них думать :). Но вот возникла задача обеспечить защиту трафика "вручную". На сервере Java, клиент - flex. Первый алгоритм с которым я познакомился (практически случайно) - DES. Алгоритм старый, имеет хорошие реализации практически на всех языках. Криптостойкость не абсолютная, как говорит wikipedia, ломается прямым перебором за 2^55 итераций. Правда для этого нужна пара открытой и закриптованной строк. Впрочем, в нашем случае его криптостойкость достаточна. 
Для серверной части используем классы javax.crypto.*. Код примерно такой:


  1. public class DesCrypter {
  2.  
  3.     Cipher ecipher;
  4.     Cipher dcipher;
  5.  
  6.     /**
  7.      * Конструктор
  8.      * @param key секретный ключ алгоритма DES
  9.      * @throws NoSuchAlgorithmException
  10.      * @throws NoSuchPaddingException
  11.      * @throws InvalidKeyException
  12.      */
  13.     public DesCrypter(String keystr) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException {
  14.         DESKeySpec desKeySpec = new DESKeySpec(keystr.getBytes());
  15.         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
  16.         SecretKey key = keyFactory.generateSecret(desKeySpec);
  17.         ecipher = Cipher.getInstance("DES");
  18.         dcipher = Cipher.getInstance("DES");
  19.         ecipher.init(Cipher.ENCRYPT_MODE, key);
  20.         dcipher.init(Cipher.DECRYPT_MODE, key);
  21.     }
  22.  
  23.     /**
  24.      * Функция шифровнаия
  25.      * @param str строка открытого текста
  26.      * @return зашифрованная строка в формате Base64
  27.      */
  28.     public String encrypt(String str) throws UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException {
  29.         byte[] utf8 = str.getBytes("UTF8");
  30.         byte[] enc = ecipher.doFinal(utf8);
  31.         return new sun.misc.BASE64Encoder().encode(enc);
  32.     }
  33.  
  34.     /**
  35.      * Функция расшифрования
  36.      * @param str зашифрованная строка в формате Base64
  37.      * @return расшифрованная строка
  38.      */
  39.     public String decrypt(String str) throws IOException, IllegalBlockSizeException, BadPaddingException {
  40.         byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
  41.         byte[] utf8 = dcipher.doFinal(dec);
  42.         return new String(utf8, "UTF8");
  43.     }
  44.  
  45. }

На клиентской стороне используем библиотеку as3crypto. С её помощью делаем реализацию шифрования на ActionScript 3.5:


  1. /**
  2. * @param string Cтрока для зашифровки
  3. * @param passString Пароль
  4. */
  5. public static function encryptString(string:String, passString:String):String {
  6.     var key:ByteArray        = Hex.toArray(Hex.fromString(passString+postfix));
  7.     var plainText:ByteArray    = Hex.toArray(Hex.fromString(string));
  8.     var cipher:ICipher = Crypto.getCipher("simple-des-ecb", key);
  9.     cipher.encrypt(plainText);
  10.     return Base64.encodeByteArray(plainText);
  11. }
  12.  
  13. /**
  14. * @param string Cтрока для расшифровки
  15. * @param passString Пароль
  16. */
  17. public static function decryptString(string:String, passString:String):String {
  18.     var key:ByteArray        = Hex.toArray(Hex.fromString(passString+postfix));
  19.     var plainText:ByteArray    = Hex.toArray(string);
  20.     var cipher:ICipher = Crypto.getCipher("simple-des-ecb", key);
  21.     cipher.decrypt(plainText);
  22.     return(Hex.toString(Hex.fromArray(plainText)));
  23. }

Никаких неожиданностей не было, всё заработало сразу. Единственная особенность: функции шифрования работают с битовыми массивами, а передаём мы строки. При создании строки играет роль (часто губительную) кодировка. Чтобы избежать неприятностей с ней, везде используем Base64-кодирование результата.

Комментариев нет:

Отправить комментарий