2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.satel.internal.protocol;
15 import java.security.GeneralSecurityException;
16 import java.security.Key;
18 import javax.crypto.Cipher;
19 import javax.crypto.spec.SecretKeySpec;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
24 * Helper class for encrypting ETHM-1 messages.
26 * @author Krzysztof Goworek - Initial contribution
29 public class EncryptionHelper {
31 private Cipher encipher;
32 private Cipher decipher;
35 * Creates new instance of encryption helper with given key.
37 * @param keyString key for integration encryption
38 * @throws GeneralSecurityException on JCE errors
40 public EncryptionHelper(String keyString) throws GeneralSecurityException {
41 // we have to check if 192bit support is enabled
42 if (Cipher.getMaxAllowedKeyLength("AES") < 192) {
43 throw new GeneralSecurityException("JCE does not support 192-bit keys");
46 // build encryption/decryption key based on given password
47 byte passwordBytes[] = keyString.getBytes();
48 byte[] keyBytes = new byte[24];
50 for (int i = 0; i < 12; ++i) {
51 keyBytes[i] = keyBytes[i + 12] = (i < passwordBytes.length) ? passwordBytes[i] : 0x20;
54 // create objects for encryption/decryption
55 this.key = new SecretKeySpec(keyBytes, "AES");
56 this.encipher = Cipher.getInstance("AES/ECB/NoPadding");
57 this.encipher.init(Cipher.ENCRYPT_MODE, this.key);
58 this.decipher = Cipher.getInstance("AES/ECB/NoPadding");
59 this.decipher.init(Cipher.DECRYPT_MODE, this.key);
63 * Decrypts given buffer of bytes in place.
67 * @throws GeneralSecurityException
68 * on decryption errors
70 public void decrypt(byte buffer[]) throws GeneralSecurityException {
71 byte[] cv = new byte[16];
72 byte[] c = new byte[16];
73 byte[] temp = new byte[16];
74 int count = buffer.length;
76 cv = this.encipher.doFinal(cv);
77 for (int index = 0; count > 0;) {
80 System.arraycopy(buffer, index, temp, 0, 16);
81 System.arraycopy(buffer, index, c, 0, 16);
82 c = this.decipher.doFinal(c);
83 for (int i = 0; i < 16; ++i) {
87 System.arraycopy(c, 0, buffer, index, 16);
90 System.arraycopy(buffer, index, c, 0, count);
91 cv = this.encipher.doFinal(cv);
92 for (int i = 0; i < 16; ++i) {
95 System.arraycopy(c, 0, buffer, index, count);
102 * Encrypts given buffer of bytes in place.
104 * @param buffer bytes to encrypt
105 * @throws GeneralSecurityException on encryption errors
107 public void encrypt(byte buffer[]) throws GeneralSecurityException {
108 byte[] cv = new byte[16];
109 byte[] p = new byte[16];
110 int count = buffer.length;
112 cv = this.encipher.doFinal(cv);
113 for (int index = 0; count > 0;) {
116 System.arraycopy(buffer, index, p, 0, 16);
117 for (int i = 0; i < 16; ++i) {
120 p = this.encipher.doFinal(p);
121 System.arraycopy(p, 0, cv, 0, 16);
122 System.arraycopy(p, 0, buffer, index, 16);
125 System.arraycopy(buffer, index, p, 0, count);
126 cv = this.encipher.doFinal(cv);
127 for (int i = 0; i < 16; ++i) {
130 System.arraycopy(p, 0, buffer, index, count);