]> git.basschouten.com Git - openhab-addons.git/blob
2cd93d539cb9e2bf23a3ef1a28f2e29b96517f4c
[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.kostalinverter.internal.thirdgeneration;
14
15 import static org.openhab.binding.kostalinverter.internal.thirdgeneration.ThirdGenerationBindingConstants.*;
16
17 import java.security.InvalidKeyException;
18 import java.security.MessageDigest;
19 import java.security.NoSuchAlgorithmException;
20 import java.security.SecureRandom;
21 import java.security.spec.InvalidKeySpecException;
22 import java.util.Base64;
23 import java.util.Random;
24
25 import javax.crypto.Mac;
26 import javax.crypto.SecretKeyFactory;
27 import javax.crypto.spec.PBEKeySpec;
28 import javax.crypto.spec.SecretKeySpec;
29
30 /**
31  * The {@link ThirdGenerationEncryptionHelper} is responsible for handling the encryption for the authentication
32  * handlers.
33  *
34  * @author RenĂ© Stakemeier - Initial contribution
35  */
36 final class ThirdGenerationEncryptionHelper {
37
38     private ThirdGenerationEncryptionHelper() {
39     }
40
41     /**
42      * This method generates the HMACSha256 encrypted value of the given value
43      *
44      * @param password Password used for encryption
45      * @param valueToEncrypt value to encrypt
46      * @return encrypted value
47      * @throws InvalidKeyException thrown if the key generated from the password is invalid
48      * @throws NoSuchAlgorithmException thrown if HMAC SHA 256 is not supported
49      */
50     static byte[] getHMACSha256(byte[] password, String valueToEncrypt)
51             throws InvalidKeyException, NoSuchAlgorithmException {
52         SecretKeySpec signingKey = new SecretKeySpec(password, HMAC_SHA256_ALGORITHM);
53         Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
54         mac.init(signingKey);
55         mac.update(valueToEncrypt.getBytes());
56         return mac.doFinal();
57     }
58
59     /**
60      * This methods generates the client proof.
61      * It is calculated as XOR between the {@link clientSignature} and the {@link serverSignature}
62      *
63      * @param clientSignature client signature
64      * @param serverSignature server signature
65      * @return client proof
66      */
67     static String createClientProof(byte[] clientSignature, byte[] serverSignature) {
68         byte[] result = new byte[clientSignature.length];
69         for (int i = 0; i < clientSignature.length; i++) {
70             result[i] = (byte) (0xff & (clientSignature[i] ^ serverSignature[i]));
71         }
72         return Base64.getEncoder().encodeToString(result);
73     }
74
75     /**
76      * Create the PBKDF2 hash
77      *
78      * @param password password
79      * @param salt salt
80      * @param rounds rounds
81      * @return hash
82      * @throws NoSuchAlgorithmException if PBKDF2WithHmacSHA256 is not supported
83      * @throws InvalidKeySpecException if the key specification is not supported
84      */
85     static byte[] getPBKDF2Hash(String password, byte[] salt, int rounds)
86             throws NoSuchAlgorithmException, InvalidKeySpecException {
87         PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, rounds, 256);
88         SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
89         return skf.generateSecret(spec).getEncoded();
90     }
91
92     /**
93      * Create the SHA256 hash value for the given byte array
94      *
95      * @param valueToHash byte array to get the hash value for
96      * @return the hash value
97      * @throws NoSuchAlgorithmException if SHA256 is not supported
98      */
99     static byte[] getSha256Hash(byte[] valueToHash) throws NoSuchAlgorithmException {
100         return MessageDigest.getInstance(SHA_256_HASH).digest(valueToHash);
101     }
102
103     /**
104      * Create the nonce (numbers used once) for the client for communication
105      *
106      * @return nonce
107      */
108     static String createClientNonce() {
109         Random generator = new SecureRandom();
110
111         // Randomize the random generator
112         byte[] randomizeArray = new byte[1024];
113         generator.nextBytes(randomizeArray);
114
115         // 3 words of 4 bytes are required for the handshake
116         byte[] nonceArray = new byte[12];
117         generator.nextBytes(nonceArray);
118
119         // return the base64 encoded value of the random words
120         return Base64.getMimeEncoder().encodeToString(nonceArray);
121     }
122 }