]> git.basschouten.com Git - openhab-addons.git/blob
0b87f20bf30e4c783f4ef48e9349c3c7c02a5df5
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.satel.internal.protocol;
14
15 import java.security.GeneralSecurityException;
16 import java.security.Key;
17
18 import javax.crypto.Cipher;
19 import javax.crypto.spec.SecretKeySpec;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22
23 /**
24  * Helper class for encrypting ETHM-1 messages.
25  *
26  * @author Krzysztof Goworek - Initial contribution
27  */
28 @NonNullByDefault
29 public class EncryptionHelper {
30     private Key key;
31     private Cipher encipher;
32     private Cipher decipher;
33
34     /**
35      * Creates new instance of encryption helper with given key.
36      *
37      * @param keyString key for integration encryption
38      * @throws GeneralSecurityException on JCE errors
39      */
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");
44         }
45
46         // build encryption/decryption key based on given password
47         byte[] passwordBytes = keyString.getBytes();
48         byte[] keyBytes = new byte[24];
49
50         for (int i = 0; i < 12; ++i) {
51             keyBytes[i] = keyBytes[i + 12] = (i < passwordBytes.length) ? passwordBytes[i] : 0x20;
52         }
53
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);
60     }
61
62     /**
63      * Decrypts given buffer of bytes in place.
64      *
65      * @param buffer
66      *            bytes to decrypt
67      * @throws GeneralSecurityException
68      *             on decryption errors
69      */
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;
75
76         cv = this.encipher.doFinal(cv);
77         for (int index = 0; count > 0;) {
78             if (count > 15) {
79                 count -= 16;
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) {
84                     c[i] ^= cv[i];
85                     cv[i] = temp[i];
86                 }
87                 System.arraycopy(c, 0, buffer, index, 16);
88                 index += 16;
89             } else {
90                 System.arraycopy(buffer, index, c, 0, count);
91                 cv = this.encipher.doFinal(cv);
92                 for (int i = 0; i < 16; ++i) {
93                     c[i] ^= cv[i];
94                 }
95                 System.arraycopy(c, 0, buffer, index, count);
96                 count = 0;
97             }
98         }
99     }
100
101     /**
102      * Encrypts given buffer of bytes in place.
103      *
104      * @param buffer bytes to encrypt
105      * @throws GeneralSecurityException on encryption errors
106      */
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;
111
112         cv = this.encipher.doFinal(cv);
113         for (int index = 0; count > 0;) {
114             if (count > 15) {
115                 count -= 16;
116                 System.arraycopy(buffer, index, p, 0, 16);
117                 for (int i = 0; i < 16; ++i) {
118                     p[i] ^= cv[i];
119                 }
120                 p = this.encipher.doFinal(p);
121                 System.arraycopy(p, 0, cv, 0, 16);
122                 System.arraycopy(p, 0, buffer, index, 16);
123                 index += 16;
124             } else {
125                 System.arraycopy(buffer, index, p, 0, count);
126                 cv = this.encipher.doFinal(cv);
127                 for (int i = 0; i < 16; ++i) {
128                     p[i] ^= cv[i];
129                 }
130                 System.arraycopy(p, 0, buffer, index, count);
131                 count = 0;
132             }
133         }
134     }
135 }