M
M
Matthew7772021-05-21 18:38:40
Java
Matthew777, 2021-05-21 18:38:40

How to encrypt with javax.crypto.Cipher using your own key?

Hey! I need a simple solution to a problem (I'm a beginner). It consists in taking a certain 16 HEX key and encrypting another 16 HEX key with it. The algorithm needs 128 AES/ECB/NoPadding. It is in this format that the device authorization parameter of the MiBand 2 fitness bracelet is perceived.
But all the solutions that I managed to find work through creating a key using "javax.crypto.spec.SecretKeySpec".
I tried to send the key to cipher.init as bytes, but it says "argument mismatch; byte[] cannot be converted to java.security.Key", other formats also give an error. How can I come to a decision?

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();
                                                         }


}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
O
Odissey Nemo, 2021-05-30
@Matthew777

Here is a thing that works, encrypts and decrypts:

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 ---" );
    }

}

I did it a long time ago and completely forgot all the details: o).
An unspecified Text.trimRight(String) simply trims all empty characters to the right of the last significant character. Text.isEmpty(String) checks if the string ("", null) is empty or not.
The Base64 class converts byte arrays to a Base64 character array and vice versa.
The algorithm you have chosen requires input strings that are a multiple of 16 characters, i.e. 16,32,48,64 etc.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question