android - Android 试图从公钥字节数组中获取公钥:java.lang.IllegalArgumentException: Invalid point encoding 0x30
问题描述
我应该接收 HEX 格式的服务器公钥(“ECDH”,“secp256k1”),未压缩(65 字节),在 Android 中生成我自己的X.509
格式(88 字节)公钥,然后生成共享秘密,必须是 32 字节。现在,当我想获取服务器公钥时,我遇到了这个错误:
java.security.spec.InvalidKeySpecException:无效的 KeySpec:点不在曲线上
过程:
首先我生成自己的公钥,然后将服务器 HEX 密钥转换为字节数组:serverKey.getBytes()
,然后将其放入下面的另一种方法中:
Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
KeyPairGenerator kpgen =KeyPairGenerator.getInstance("ECDH", "BC");
ECGenParameterSpec genspec = new ECGenParameterSpec("secp256k1");
kpgen.initialize(genspec);
KeyPair localKeyPair = kpgen.generateKeyPair();
ECPublicKey remoteKey = decodeECPublicKey(serverKey.getBytes());
KeyAgreement localKA = KeyAgreement.getInstance("ECDH");
localKA.init(keyPair.getPrivate());
localKA.doPhase((ECPublicKey) remoteKey, true);
byte[] localSecret = localKA.generateSecret();
decodeECPublicKey
是:
public static decodeECPublicKey getPublicKeyFromBytes(byte[] pubKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
KeyFactory kf = KeyFactory.getInstance("ECDH", new BouncyCastleProvider());
ECNamedCurveSpec params = new ECNamedCurveSpec("secp256k1", spec.getCurve(), spec.getG(), spec.getN());
ECPoint point = ECPointUtil.decodePoint(params.getCurve(), pubKey);
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);
ECPublicKey pk = (ECPublicKey) kf.generatePublic(pubKeySpec);
return pk;
}
执行时会产生此错误:
java.lang.IllegalArgumentException:无效的点编码 0x30
我究竟做错了什么?
编辑:
好的。错误的部分要serverKey.getBytes()
感谢@Topaco。既然我有了,localSecret
我想String
用 AES-256-CBC 算法加密 a,使用前 16 个字节localSecret
作为 iv,第二个字节作为密钥。我已经编写了这段代码,但是当我将结果发送到服务器时,它会产生错误:
public static byte[] enc(byte[] key, String toBeEnc) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException {
Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[16];
System.arraycopy(key, 0, iv, 0, iv.length);
byte[] keyByte = new byte[16];
System.arraycopy(key, 16, keyByte, 0, keyByte.length);
Key keyF = new SecretKeySpec(keyByte, "AES");
ecipher.init(Cipher.ENCRYPT_MODE, keyF, new IvParameterSpec(iv));
byte[] enc = ecipher.doFinal(toBeEnc.getBytes(StandardCharsets.UTF_8));
return enc;
}
解决方案
推荐阅读
- python - 如何在保持原始文件扩展名的同时保存修改后的图像文件名
- excel - 将不同工作表上的变量命名范围导出到一个 pdf
- r - 如何在不带引号(R)的函数参数中使用字符串?
- regex - 正则表达式:在 PowerShell 中删除行尾括号中的数字
- database - 使用一个查询获取集合中的每个项目
- git - 将 git 分支或标签名称设置为打包的 jar
- php - PHP 检查和调整图像大小以满足 Instagram 要求
- vba - (VBA)在 csv 文件上使用 OLEDB 库时出现“没有为一个或多个必需参数提供值”错误,但存在字段
- jenkins - jenkins - 覆盖代理上的环境变量
- java - Lombok 扩展方法:流行/优先级?