» Программирование Android

Использование алгоритма DES для шифрования в Android

DES, или Data Encryption Standard, — это симметричный алгоритм шифрования, который был разработан IBM и утвержден в далеком 1977 официальным стандартом в США. Применяется данный блочный алгоритм с симметричным ключом во многих криптографических системах. Мы разберемся с шифрованием данных с использованием данного алгоритма применимо к операционной системе Android.

Еще несколько слов по самой сути данного алгоритма. Как мы уже сказали, алгоритм блочный и использует симметричный 64-битный ключ, из которых непосредственно при шифровании применяется только 56 бит. Остальные 8 бит используются для контроля четности, то есть они устанавливаются так, чтобы каждый из всех 8 байт ключа имел нечетное значение. Шифруемая по данному алгоритму информация обрабатывается блоками по 64 бита, в процессе обработки каждый блок подвергается модификации при помощи ключа в интерационной процедуре, состоящей из 16 циклов.

В Android для шифрования применяются классы пакета javax.crypto. Данный пакет входит в состав Android SDK. Класс javax.crypto.Cipher реализует все базовые функции всех распространенных криптографических алгоритмов для шифрования данных, включая AES, RSA, DES и нескольких других. Для того, чтобы создать экземпляр такого класса, используется статистический метод Cipher.getInstance. Данный метод в качестве параметра получает имя криптографического шифрующего алгоритма:

Cipher chr = Cipher.getInstance(«DES»);

После этого нужно настроить экземпляр класса javax.crypto.Cipher с указанием, в каком режиме он должен работать: в режиме дешифрования или шифрования:

chr.init(Cipher.ENCRYPT_MODE, key);

Параметр key в данной строке – это ключ шифрования криптографического алгоритма DES. Параметр имеет тип javax.crypto.SecretKey и его можно создать следующим образом:

javax.crypto.KeyGenerator.SecretKey key = KeyGenerator.getInstance(«DES»).generateKey()

В алгоритме DES используется симметричное шифрование, а потому для всех операций применяется один и тот же ключ или «master key». Настройка ключа происходит следующим образом. Во-первых, на основе ключа в виде текста формируется байтовый массив, который может быть использован алгоритмом DES для шифрования данных:

private static byte[] getRawKey() throws Exception {

   // seed – это текстовый ключ шифрования

     KeyGenerator kgen = KeyGenerator.getInstance(«DES»);

   //  SecureRandom создает псевдослучайные последовательности

   //  http://developer.android.com/reference/java/security/SecureRandom.html

     SecureRandom sr = SecureRandom.getInstance(«SHA1PRNG»);

  sr.setSeed(seed.getBytes());

     kgen.init(56, sr); // здесь на основе главного ключа создается 56-битный ключ для DES

     SecretKey skey = kgen.generateKey();

     byte[] raw = skey.getEncoded();

     return raw;

 }

После данной операции на основе байтов ключа происходит создание объекта класса SecretKeySpec:

javax.crypto.spec.SecretKeySpec

             key = new  javax.crypto.spec.SecretKeySpec(getRawKey(), «DES»);

Созданный SecretKeySpec затем передается в объект класса javax.crypto.Cipher, который, в свою очередь, непосредственно производит шифрацию или же дешифрацию информации посредством вызова метода doFinal:

javax.crypto.spec.SecretKeySpec

             key = new  javax.crypto.spec.SecretKeySpec(getRawKey(), «DES»);

        Cipher ecipher = Cipher.getInstance(«DES»);

        ecipher.init(Cipher.ENCRYPT_MODE, key);

       // src – это строка которую нужно зашифровать

       byte[] utf8 = src.getBytes(«UTF8»);

 

        // получение зашифрованного массива байт

        byte[] enc = ecipher.doFinal(utf8);

Ниже мы приведем пример класса, который реализовывает алгоритм шифрования DES и дешифрацию применительно к тексту с указанным паролем seed. Зашифрованные байты затем преобразовываются в строки – так их удобнее хранить в SQLite.

/*
 * DES encrypting/decrypting for text data
 */
 
 
import java.security.*;
import javax.crypto.*;
 
public class SimpleDESCryptoProvider {
    
    public static final String seed = "AM6ROFFBABFAKILLEMALL";
 
    public static String decrypt(String src)
    {
 
       try{
        javax.crypto.spec.SecretKeySpec
             key = new  javax.crypto.spec.SecretKeySpec(getRawKey(), "DES");
        Cipher ecipher = Cipher.getInstance("DES");
        ecipher.init(Cipher.DECRYPT_MODE, key);
    
        byte[] utf8 = toByte(src);
 
        // Descrypt
        byte[] dec= ecipher.doFinal(utf8);
 
        return new String( dec  );
        }
        catch(Exception exc )
        {
           try{
               exc.printStackTrace();
            }catch(Exception exc2){}
 
        }
       return src;
 
    }
 
     public static String encrypt(String src)
    {
       try{
        javax.crypto.spec.SecretKeySpec
             key = new  javax.crypto.spec.SecretKeySpec(getRawKey(), "DES");
        Cipher ecipher = Cipher.getInstance("DES");
        ecipher.init(Cipher.ENCRYPT_MODE, key);
        
        byte[] utf8 = src.getBytes("UTF8");
 
        // Encrypt
        byte[] enc = ecipher.doFinal(utf8);
 
        return toHex(enc);
        }
        catch(Exception exc )
        {
           try{
              exc.printStackTrace();
            }catch(Exception exc2){}
 
        }
       return src;
    }
 
     private static byte[] getRawKey() throws Exception {
     KeyGenerator kgen = KeyGenerator.getInstance("DES");
  SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
  sr.setSeed(seed.getBytes());
     kgen.init(56, sr);
     SecretKey skey = kgen.generateKey();
     byte[] raw = skey.getEncoded();
     return raw;
 }
 
    // эти методы используются для конвертации байтов в ASCII символы
 
     public static String toHex(String txt) {
  return toHex(txt.getBytes());
 }
 public static String fromHex(String hex) {
  return new String(toByte(hex));
 }
 
 public static byte[] toByte(String hexString) {
  int len = hexString.length()/2;
  byte[] result = new byte[len];
  for (int i = 0; i < len; i++)
   result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
  return result;
 }
 
 public static String toHex(byte[] buf) {
  if (buf == null)
   return "";
  StringBuffer result = new StringBuffer(2*buf.length);
  for (int i = 0; i < buf.length; i++) {
   appendHex(result, buf[i]);
  }
  return result.toString();
 }
 private final static String HEX = "0123456789ABCDEF";
 private static void appendHex(StringBuffer sb, byte b) {
  sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
 }
}

Использование класса может выглядеть следующим образом:

String s = "Привет.";
        String d = SimpleDESCryptoProvider.encrypt(s);
        System.out.println(d);
        s = SimpleDESCryptoProvider.decrypt(d);
        System.out.println(s);

Александр
2015-03-01 09:04:53
Работает на виртуальном девайсе (2.3.3) не работает на реальном (4.2.2)