Освой программирование играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Криптография

Cryptocat

Для привлечения внимания был использован логотип open-source программы Cryptocat, не имеющая отношения к данной статье

Я не разбираюсь в криптографии и статья выложена только для ознакомления.

Android имеет в своём составе пакет javax.crypto с классами, которые отвечают за шифрование, дешифрование, ключи и т.п. Если вы занимались этой темой в Java, то многое будет знакомо. Поддерживаются популярные алгоритмы AES и RSA.

Список провайдеров

Для начала получим список провайдеров и поддерживаемые ими сервисы и алгоритмы.


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="Список провайдеров" />

    <ScrollView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal" />
    </ScrollView>

</LinearLayout>

Код по щелчку кнопки


public void onClick(View view) {
    TextView textView = (TextView) findViewById(R.id.textView);
    textView.setText(getSecurityProviders());
}

public String getSecurityProviders() {

    String result = "";

    Provider[] providers = Security.getProviders();

    for (int i = 0; i < providers.length; i++) {
        // Получим все сервисы для выбранного провайдера
        Set<Object> ks = providers[i].keySet();
        Set<String> servicetypes = new TreeSet<>();
        for (Iterator<Object> it = ks.iterator(); it.hasNext(); ) {
            String k = it.next().toString();
            k = k.split(" ")[0];
            if (k.startsWith("Alg.Alias."))
                k = k.substring(10);

            servicetypes.add(k.substring(0, k.indexOf('.')));
        }

        // Получим все алгоритмы для выбранного типа сервиса
        int s = 1;
        for (Iterator<String> its = servicetypes.iterator(); its.hasNext(); ) {
            String stype = its.next();
            Set<String> algorithms = new TreeSet<>();
            for (Iterator<Object> it = ks.iterator(); it.hasNext(); ) {
                String k = it.next().toString();
                k = k.split(" ")[0];
                if (k.startsWith(stype + "."))
                    algorithms.add(k.substring(stype.length() + 1));
                else if (k.startsWith("Alg.Alias." + stype + "."))
                    algorithms.add(k.substring(stype.length() + 11));
            }

            int a = 1;
            for (Iterator<String> ita = algorithms.iterator(); ita.hasNext(); ) {
                result += ("[П#" + (i + 1) + ":" + providers[i].getName() + "]" +
                        "[С#" + s + ":" + stype + "]" +
                        "[А#" + a + ":" + ita.next() + "]\n");
                a++;
            }
            s++;
        }
    }
    return result;
}

Get Security Providers

Симметричное шифрование AES

Популярный алгоритм симметричного шифрования Advanced Encryption Standard (AES).

Зададим тестовую строку, зашифруем и расшифруем её.


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textViewOriginal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

    <TextView
        android:id="@+id/textViewEncoded"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

    <TextView
        android:id="@+id/textViewDecoded"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

</LinearLayout>

Весь процесс происходит в методе onCreate():


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Original text
    String testText = "А у нас сегодня кошка родила вчера котят";
    TextView originalTextView = (TextView) findViewById(R.id.textViewOriginal);
    originalTextView.setText("[ORIGINAL]:\n" + testText + "\n");

    // Set up secret key spec for 128-bit AES encryption and decryption
    SecretKeySpec sks = null;
    try {
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        sr.setSeed("any data used as random seed".getBytes());
        KeyGenerator kg = KeyGenerator.getInstance("AES");
        kg.init(128, sr);
        sks = new SecretKeySpec((kg.generateKey()).getEncoded(), "AES");
    } catch (Exception e) {
        Log.e("Crypto", "AES secret key spec error");
    }

    // Encode the original data with AES
    byte[] encodedBytes = null;
    try {
        Cipher c = Cipher.getInstance("AES");
        c.init(Cipher.ENCRYPT_MODE, sks);
        encodedBytes = c.doFinal(testText.getBytes());
    } catch (Exception e) {
        Log.e("Crypto", "AES encryption error");
    }

    TextView encodedTextView = (TextView)findViewById(R.id.textViewEncoded);
    encodedTextView.setText("[ENCODED]:\n" +
            Base64.encodeToString(encodedBytes, Base64.DEFAULT) + "\n");

    // Decode the encoded data with AES
    byte[] decodedBytes = null;
    try {
        Cipher c = Cipher.getInstance("AES");
        c.init(Cipher.DECRYPT_MODE, sks);
        decodedBytes = c.doFinal(encodedBytes);
    } catch (Exception e) {
        Log.e("Crypto", "AES decryption error");
    }

    TextView decodedTextView = (TextView)findViewById(R.id.textViewDecoded);
    decodedTextView.setText("[DECODED]:\n" + new String(decodedBytes) + "\n");
}

AES

Ассиметричное шифрование RSA

Разметку оставляем без изменений. Используем другой алгоритм RSA:


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Original text
    String testText = "А у нас сегодня кошка родила вчера котят";
    TextView originalTextView = (TextView) findViewById(R.id.textViewOriginal);
    originalTextView.setText("[ORIGINAL]:\n" + testText + "\n");

    // Generate key pair for 1024-bit RSA encryption and decryption
    Key publicKey = null;
    Key privateKey = null;
    try {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024);
        KeyPair kp = kpg.genKeyPair();
        publicKey = kp.getPublic();
        privateKey = kp.getPrivate();
    } catch (Exception e) {
        Log.e("Crypto", "RSA key pair error");
    }

    // Encode the original data with RSA private key
    byte[] encodedBytes = null;
    try {
        Cipher c = Cipher.getInstance("RSA");
        c.init(Cipher.ENCRYPT_MODE, privateKey);
        encodedBytes = c.doFinal(testText.getBytes());
    } catch (Exception e) {
        Log.e("Crypto", "RSA encryption error");
    }
    TextView encodedTextView = (TextView)findViewById(R.id.textViewEncoded);
    encodedTextView.setText("[ENCODED]:\n" +
            Base64.encodeToString(encodedBytes, Base64.DEFAULT) + "\n");

    // Decode the encoded data with RSA public key
    byte[] decodedBytes = null;
    try {
        Cipher c = Cipher.getInstance("RSA");
        c.init(Cipher.DECRYPT_MODE, publicKey);
        decodedBytes = c.doFinal(encodedBytes);
    } catch (Exception e) {
        Log.e("Crypto", "RSA decryption error");
    }

    TextView decodedTextView = (TextView)findViewById(R.id.textViewDecoded);
    decodedTextView.setText("[DECODED]:\n" + new String(decodedBytes) + "\n");
}

RSA

По мотивам статьи Android Encryption with the Android Cryptography API

Реклама