Matthew777
@Matthew777

Как зашифровать посредством javax.crypto.Cipher с помощью своего ключа?

Привет! Я нуждаюсь в простом решении проблемы(я новичек). Она состоит в том, что бы взять определенный 16 ХЕХ ключ, и зашифровать им другой 16 HEX ключ. Алгоритм необходим 128 AES/ECB/NoPadding. Именно в таком формате воспринимает параметр авторизации устройства фитнес-браслета MiBand 2.
Но все решения, что мне удалось найти работают через создание ключа посредством "javax.crypto.spec.SecretKeySpec".
Я пытался послать на cipher.init ключ в виде байтов, но мне пишет "argument mismatch; byte[] cannot be converted to java.security.Key", другие форматы тоже выдают ошибку. Как я могу прийти к решению?

package com.company;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class Main
{ public static void main(String[] argv) {
        String value = "9CC07199FECA0313403475ED62FEC727";
        System.out.println("encriptVal = " + encrypt(value) );
                                           }


    public static String encrypt(String value) {
        try {
            SecretKeySpec sks = new SecretKeySpec(hexStringToByteArray("30313233343536373839404142434445"), "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, sks, cipher.getParameters());
            byte[] encrypted = cipher.doFinal(value.getBytes());
            return byteArrayToHexString(encrypted);
            }

        catch (Exception e) {
            throw new RuntimeException(e);
                            }
                                               }

    private static byte[] hexStringToByteArray(String syc) {
        byte[] b = new byte[syc.length() / 2];
        for (int i = 0; i < b.length; i++) {
            int index = i * 2;
            int v = Integer.parseInt(syc.substring(index, index + 2), 16);
            b[i] = (byte) v;
                                           }
        return b;
                                                         }


    private static String byteArrayToHexString(byte[] b) {
        StringBuilder sb = new StringBuilder(b.length * 2);
        for (int i = 0; i < b.length; i++) {
            int v = b[i] & 0xff;
            if (v < 16) {
                sb.append('0');
            }
            sb.append(Integer.toHexString(v));
                                           }
        return sb.toString().toUpperCase();
                                                         }


}
  • Вопрос задан
  • 234 просмотра
Решения вопроса 1
@odissey_nemo
Программист, ГИС-системы, растры, космоснимки
Вот такая штука работает, зашифровывает и расшифровывает :

package su.common.crypto;

import org.apache.commons.lang.StringUtils;
import su.common.misc.Text;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;

/**
 * Created in su.common.crypto.<br>
 * User: ******<br>
 * Date: 30.08.2011<br>
 * Time: 17:12:45<br>
 */
public class SimpleEncDec {
    private static final String DEFAULT_ALGO_NAME = "AES";
    //	private static final String DEFAULT_CIPHER_NAME = "AES/ECB/PKCS5Padding";
    private static final String DEFAULT_CIPHER_NAME = "AES/ECB/NoPadding";
    private KeyGenerator m_keygen;
    private SecretKey m_key = m_keygen.generateKey();
    private Cipher m_cipherIn;
    private Cipher m_cipherOut;

    public SimpleEncDec( String algorithmName ) throws NoSuchAlgorithmException {
//        KeyGenerator m_keygen;
        if ( Text.isEmpty( algorithmName ) )
            m_keygen = KeyGenerator.getInstance( DEFAULT_ALGO_NAME );
        else
            m_keygen = KeyGenerator.getInstance( algorithmName );

        // Create the cipher
        try {
            m_cipherIn = Cipher.getInstance( DEFAULT_CIPHER_NAME );
            m_cipherIn.init( Cipher.ENCRYPT_MODE, m_key );
            m_cipherOut = Cipher.getInstance( DEFAULT_CIPHER_NAME );
            m_cipherOut.init( Cipher.DECRYPT_MODE, m_key );
        } catch ( Exception e ) {
            e.printStackTrace();
        }
    }

    public SimpleEncDec() throws NoSuchAlgorithmException, NoSuchPaddingException {
        this( null );
    }

    public String encrypt( String arg, String password ) {
        try {
            byte[] res = m_cipherIn.doFinal( arg.getBytes() );
            return Base64.encode( res );
        } catch ( Exception e ) {
            System.err.println(e);
        }
        return null;
    }

    public String decrypt( String arg, String password ) {
        byte[] res = Base64.decode( arg );
        try {
            res = m_cipherOut.doFinal( res );
            return new String( res );
        } catch ( Exception e ) {
            System.err.println(e);
        }
        return null;
    }

    public static String strPad16( String strToPad ) {
        final int len = strToPad.length();
        if (len % 16 == 0)
            return strToPad;
        return StringUtils.rightPad( strToPad, (len + 16 - (len%16)) );
    }

    public static void main( String[] args ) throws NoSuchAlgorithmException {

        SimpleEncDec sed = new SimpleEncDec( "AES" );
        // check functionality
        final String password = "simple_password";

        String checkStr = "String to encode/decode for algorithms test";
        System.out.println( String.format( "String to encrypt: \"%s\"", strPad16(checkStr) ) );

        // encode string
        String encStr = sed.encrypt( strPad16(checkStr), password );
        System.out.println(String.format( "Encrypted into \"%s\"", encStr ) );

        final String decrypt = sed.decrypt( encStr, password );
        String decStr = Text.trimRight( decrypt );
        System.out.println( String.format( "Decrypted to \"%s\"", decStr ) );

        if ( decStr.equals( checkStr ) )
            System.out.println( "+++ Encryption/decryption works well +++" );
        else
            System.err.println( "--- Encryption/decryption doesn't work ---" );
    }

}

Делал давно и все детали забыл напрочь :o) .
Не указанный Text.trimRight(String) просто убирает все пустые символы справа, от последнего значащего символа. Text.isEmpty(String) проверяет, пуста ли строка ("", null) или нет.
Класс Base64 переводит байтовые массивы в массив символов Basе64 и обратно.

В выбранном Вами алгоритме требуются входные строки длиной кратной 16 символам, т.е. 16,32,48,64 и т.д.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы