1.先约定一个秘钥,写死,比如aabbccdd(每个产品一个)
2.app用tcp申请通信秘钥,这个请求用aabbccdd加密.
3.云端用aabbccdd解密,知道是申请秘钥,然后返回一个秘钥bbccddeeff,这里这个秘钥是用aabbccdd加密的(安全问题),
4.设备用aabbccdd解密出秘钥bbccddeeff,然后后面的通信用bbccddeeff来加解密,
5.秘钥有有效期.
风险,如果别人知道aabbccdd初始秘钥,会破解通信内容的.这个只是tcp接口,所有后面我们直接统一用https接口了.这种方案不要了.
但是有的设备用其他平台,比如电信,移动的OneNet平台,需要传输数据,对于他们,需要透传一些数据,所以还是需要用到秘钥的,这里又提供另外的解决方案;
使用ECDHE密钥交换算法交换公钥,这里可以参考
https://blog.csdn.net/mrpre/article/details/78025940
大概流程如下,
上面这个流程,可以简化一下:
1 设备烧固件的时候直接存了服务器的公钥a,少一步交互,都是存在加密芯片(安全),现在的设备基本都需要加密芯片了
2,设备另外上报一个公钥c,服务器接收到这个设备,算出共享秘钥,pubKey=前缀+c,priKey=b,这样子保证每个设备的加密因子都是不一样的,都是根据设备上报上报的公钥c计算的,这里获取到的加密因子,可以截取部分,这样子又增加破解难度.
3.采用下面这个算法,一起算出私钥,然后这个设备以后的数据都统一用这个私钥来加密来通信,除非重新上报一个公钥,加密因子才会修改.
4.因为设备有加密芯片.你输入加密字符串,直接输出解密的数据了.
5.即使服务器公钥私钥都被拿到(开发人员),但是每个设备上报的公钥不一样,也是破解单个设备,设备有加密芯片,其他设备也是安全的.
代码如下:
/**
* 加密因子
* @param pubKey
* @param priKey
* @return
* @throws Exception
*/
public static String getECHDSecret(String pubKey,String priKey) throws Exception {
try {
byte[] pubKeyBytes = ECCCoder.hexToBytes(pubKey);
X509Key x509key = new X509Key();
x509key.decode(pubKeyBytes);
ECPublicKey alicePub = (ECPublicKey) ECKeyFactory.toECKey(x509key);
byte[] privKeyBytes = ECCCoder.hexToBytes(priKey);
PKCS8Key pkcs8Key = new PKCS8Key();
pkcs8Key.decode(privKeyBytes);
ECPrivateKey alicePvt = (ECPrivateKey) ECKeyFactory.toECKey(pkcs8Key);
byte[] alicePubEncoded = alicePub.getEncoded();
KeyFactory aliceKf = KeyFactory.getInstance("EC");
PublicKey remoteBobPub = aliceKf.generatePublic(new X509EncodedKeySpec(alicePubEncoded));
KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("ECDH");
aliceKeyAgree.init(alicePvt);
aliceKeyAgree.doPhase(remoteBobPub, true);
String secret=toHex(aliceKeyAgree.generateSecret());
return secret;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}