]> git.basschouten.com Git - openhab-addons.git/blob
7747e9cd3abc91d748136172aa317f2be9fde2d4
[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.androidtv.internal.protocol.googletv;
14
15 import java.math.BigInteger;
16 import java.security.MessageDigest;
17 import java.security.NoSuchAlgorithmException;
18 import java.security.PublicKey;
19 import java.security.cert.Certificate;
20 import java.security.interfaces.RSAPublicKey;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 /**
27  * GoogleTVCommand represents a GoogleTV protocol command
28  *
29  * @author Ben Rosenblum - Initial contribution
30  */
31 @NonNullByDefault
32 public class GoogleTVUtils {
33     private static final Logger LOGGER = LoggerFactory.getLogger(GoogleTVUtils.class);
34
35     private static String processMag(final byte[] magnitude) {
36         final int length = magnitude.length;
37         if (length != 0) {
38             final BigInteger bigInteger = new BigInteger(1, magnitude);
39             final StringBuilder sb = new StringBuilder();
40             sb.append("%0");
41             sb.append(length + length);
42             sb.append("x");
43             return String.format(sb.toString(), bigInteger);
44         }
45         return "";
46     }
47
48     private static final byte[] processDigestArray(final byte[] array) {
49         int n = 0;
50         int length;
51         while (true) {
52             length = array.length;
53             if (n >= length || array[n] != 0) {
54                 break;
55             }
56             ++n;
57         }
58         final int n2 = length - n;
59         final byte[] array2 = new byte[n2];
60         System.arraycopy(array, n, array2, 0, n2);
61         return array2;
62     }
63
64     public static final byte[] processDigest(byte[] digest, Certificate clientCert, Certificate serverCert) {
65         final PublicKey clientPublicKey = clientCert.getPublicKey();
66         final PublicKey serverPublicKey = serverCert.getPublicKey();
67         processMag(digest);
68         if (clientPublicKey instanceof RSAPublicKey && serverPublicKey instanceof RSAPublicKey) {
69             final RSAPublicKey clientRSAPublicKey = (RSAPublicKey) clientPublicKey;
70             final RSAPublicKey serverRSAPublicKey = (RSAPublicKey) serverPublicKey;
71             try {
72                 final MessageDigest instance = MessageDigest.getInstance("SHA-256");
73                 final byte[] byteArray1 = clientRSAPublicKey.getModulus().abs().toByteArray();
74                 final byte[] byteArray2 = clientRSAPublicKey.getPublicExponent().abs().toByteArray();
75                 final byte[] byteArray3 = serverRSAPublicKey.getModulus().abs().toByteArray();
76                 final byte[] byteArray4 = serverRSAPublicKey.getPublicExponent().abs().toByteArray();
77                 final byte[] r1 = processDigestArray(byteArray1);
78                 final byte[] r2 = processDigestArray(byteArray2);
79                 final byte[] r3 = processDigestArray(byteArray3);
80                 final byte[] r4 = processDigestArray(byteArray4);
81                 processMag(r1);
82                 processMag(r2);
83                 processMag(r3);
84                 processMag(r4);
85                 processMag(digest);
86                 instance.update(r1);
87                 instance.update(r2);
88                 instance.update(r3);
89                 instance.update(r4);
90                 instance.update(digest);
91                 digest = instance.digest();
92                 processMag(digest);
93             } catch (NoSuchAlgorithmException e) {
94                 LOGGER.warn("NoSuchAlgorithmException Exception", e);
95             }
96         }
97         return digest;
98     }
99
100     public static String byteArrayToString(byte[] array) {
101         StringBuilder sb = new StringBuilder();
102         for (int i = 0; i < array.length; i++) {
103             sb.append((char) (array[i] & 0xFF));
104         }
105         return sb.toString();
106     }
107
108     public static String validatePIN(String pin, Certificate clientCert, Certificate serverCert) {
109         char[] charArray = pin.toCharArray();
110
111         String s1 = "" + charArray[0] + charArray[1];
112         String s2 = "" + charArray[2] + charArray[3];
113         String s3 = "" + charArray[4] + charArray[5];
114         int si1 = Integer.parseInt(s1, 16);
115         int si2 = Integer.parseInt(s2, 16);
116         int si3 = Integer.parseInt(s3, 16);
117
118         byte[] sb123 = new byte[] { (byte) si1, (byte) si2, (byte) si3 };
119         byte[] sb23 = new byte[] { (byte) si2, (byte) si3 };
120         byte[] digest = processDigest(sb23, clientCert, serverCert);
121         String digestString = GoogleTVRequest.decodeMessage(byteArrayToString(digest));
122
123         byte[] validPinB = new byte[] { digest[0], (byte) si2, (byte) si3 };
124         String validPin = GoogleTVRequest.decodeMessage(byteArrayToString(validPinB));
125         LOGGER.trace("validatePIN {} {} {} {} {} {}", sb123, digest[0], sb23, validPinB, validPin, digestString);
126
127         return digestString;
128     }
129 }