我应该接收 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;
}