2 * Copyright (c) 2010-2022 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.tplinksmarthome.internal;
15 import java.io.ByteArrayInputStream;
16 import java.io.DataInputStream;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.nio.ByteBuffer;
20 import java.nio.charset.StandardCharsets;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
25 * Util class to encypt and decrypt data to be sent to and from the smart plug.
27 * @author Hilbrand Bouwkamp - Initial contribution
30 public final class CryptUtil {
32 private static final int KEY = 171;
39 * Decrypt the byte array of the specified length. The length is necessary because the byte array might be larger
40 * than the actual content.
42 * @param data byte array containing the data
43 * @param length number of bytes in the byte array to read
44 * @return decrypted String of the byte array
45 * @throws IOException exception in case device not reachable
47 public static String decrypt(byte[] data, int length) throws IOException {
48 try (ByteArrayInputStream is = new ByteArrayInputStream(data)) {
49 return decrypt(is, length);
54 * Decrypt the byte data in the input stream. In the first 4 bytes the length of the data in the byte array is
57 * @param inputStream input stream containing length and data
58 * @return decrypted String of the inputstream
59 * @throws IOException exception in case device not reachable
61 public static String decryptWithLength(InputStream inputStream) throws IOException {
62 try (DataInputStream is = new DataInputStream(inputStream)) {
63 return decrypt(is, is.readInt());
68 * Decrypt the byte data in the input stream with the length as given.
70 * @param inputStream input stream
71 * @param length the number of bytes to read
72 * @return decrypted String of the inputstream
73 * @throws IOException exception in case device not reachable
75 private static String decrypt(InputStream inputStream, int length) throws IOException {
76 final byte[] decryptedData = new byte[length];
80 while (i < length && (in = inputStream.read()) != -1) {
81 final int nextKey = in;
82 decryptedData[i++] = (byte) (in ^ key);
85 return new String(decryptedData, StandardCharsets.UTF_8);
89 * Encrypts the string into a byte array with the first for bytes specifying the length of the given String. The
90 * length is not encrypted.
92 * @param string String to encrypt
93 * @return byte array with length and encrypted string
95 public static byte[] encryptWithLength(String string) {
96 ByteBuffer bb = ByteBuffer.allocate(4 + string.length());
97 bb.putInt(string.length());
98 bb.put(encrypt(string));
103 * Encrypts the string into a byte array.
105 * @param string String to encrypt
106 * @return byte array with encrypted string
108 public static byte[] encrypt(String string) {
109 byte[] buffer = new byte[string.length()];
110 byte key = (byte) KEY;
111 for (int i = 0; i < string.length(); i++) {
112 buffer[i] = (byte) (string.charAt(i) ^ key);