@Override protected ECPublicKeySpec createPublicKeySpec(byte[] encodedKey) throws InvalidKeySpecException, NoSuchAlgorithmException { // convert the key to the format used by BouncyCastle, which adds one byte byte[] bouncyCompressedKey = new byte[keyLengthBytes+1]; System.arraycopy(encodedKey, 0, bouncyCompressedKey, 1, keyLengthBytes); bouncyCompressedKey[0] = (byte)((bouncyCompressedKey[1] >> 1) + 2); bouncyCompressedKey[1] &= 1; // decompress into an EC point ECPoint w = ECUtils.decodePoint(ecParameterSpec.getCurve(), bouncyCompressedKey); // make a public key from the public point w ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(w, ecParameterSpec); return publicKeySpec; }
public static ECPoint decodePoint( EllipticCurve curve, byte[] encoded) { String pkg = getPackage(); try { Class<?> utilClazz = Class.forName(pkg + ".jce.ECPointUtil"); Method decodePoint = utilClazz.getDeclaredMethod( "decodePoint", EllipticCurve.class, byte[].class); return (ECPoint) decodePoint.invoke(null, curve, encoded); } catch (ClassNotFoundException e) { throw new RuntimeException("decodePoint() failed", e); } catch (NoSuchMethodException e) { throw new RuntimeException("decodePoint() failed", e); } catch (IllegalAccessException e) { throw new RuntimeException("decodePoint() failed", e); } catch (InvocationTargetException e) { throw new RuntimeException("decodePoint() failed", e); } } }
/** * * @param curveName * @param bcCurveName * @param sigName * @param keyLengthBytes Length of a byte array encoding of one (public or private) key * @throws GeneralSecurityException */ ECDH_ECDSA(String curveName, String sigName, int keyLengthBytes) throws GeneralSecurityException { super(); ecParameterSpec = ECUtils.getParameters(curveName); signatureAlg = Signature.getInstance(sigName); // Backwards-compatibility with old ECDSA-521 signatures that used SHA-256 if ("P-521".equals(curveName)) altSignatureAlg = Signature.getInstance("SHA256withECDSA"); this.keyLengthBytes = keyLengthBytes; encryptionKeyPairGenerator = KeyPairGenerator.getInstance("ECDH"); encryptionKeyPairGenerator.initialize(ecParameterSpec, appContext.random()); signingKeyPairGenerator = KeyPairGenerator.getInstance("ECDSA"); signingKeyPairGenerator.initialize(ecParameterSpec, appContext.random()); ecdhKeyFactory = KeyFactory.getInstance("ECDH"); ecdsaKeyFactory = KeyFactory.getInstance("ECDSA"); }
@Override protected byte[] toByteArray(PublicKey key) { ECPublicKey ecKey = castToEcKey(key); return ECUtils.encodePoint(ecKey.getParams(), ecKey.getW(), true); }
@Override protected byte[] toByteArray(PublicKey key) { ECPublicKey ecKey = castToEcKey(key); byte[] bouncyCompressedKey = ECUtils.encodePoint(ecKey.getParams(), ecKey.getW(), true); // shorten by one byte (bouncyCompressedKey[0] is either 2 or 3, bouncyCompressedKey[1] is either 0 or 1, so they can fit in two bits) if (bouncyCompressedKey[0]!=2 && bouncyCompressedKey[0]!=3) log.error("Illegal value in encoded EC key at byte 0: " + bouncyCompressedKey[0] + ", can only be 2 or 3."); if (bouncyCompressedKey[1]!=0 && bouncyCompressedKey[1]!=1) log.error("Illegal value in encoded EC key at byte 1: " + bouncyCompressedKey[1] + ", can only be 0 or 1."); byte[] compressedKey = Arrays.copyOfRange(bouncyCompressedKey, 1, keyLengthBytes+1); compressedKey[0] |= (bouncyCompressedKey[0]-2) << 1; return compressedKey; }
public static ECParameterSpec getParameters(String curveName) { String pkg = getPackage(); try { Class<?> ncClazz = Class.forName(pkg + ".asn1.nist.NISTNamedCurves");
@Override protected ECPublicKeySpec createPublicKeySpec(byte[] encodedKey) throws InvalidKeySpecException, NoSuchAlgorithmException { // decompress into an EC point ECPoint w = ECUtils.decodePoint(ecParameterSpec.getCurve(), encodedKey); // make a public key from the public point w ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(w, ecParameterSpec); return publicKeySpec; }
public static byte[] encodePoint( ECParameterSpec ecSpec, ECPoint point, boolean withCompression) { String pkg = getPackage(); try { Class<?> utilClazz = Class.forName(pkg + ".jcajce.provider.asymmetric.util.EC5Util"); Class<?> cvClazz = Class.forName(pkg + ".math.ec.ECCurve"); Class<?> ptClazz = Class.forName(pkg + ".math.ec.ECPoint"); // Implement EC5Util.convertPoint() ourselves // Workaround for https://github.com/bcgit/bc-java/issues/262 Method convertCurve = utilClazz.getDeclaredMethod( "convertCurve", EllipticCurve.class); Method createPoint = cvClazz.getDeclaredMethod( "createPoint", BigInteger.class, BigInteger.class, boolean.class); Method getEncoded = ptClazz.getDeclaredMethod("getEncoded"); Object bcCurve = convertCurve.invoke(null, ecSpec.getCurve()); Object bcPoint = createPoint.invoke(bcCurve, point.getAffineX(), point.getAffineY(), withCompression); return (byte[]) getEncoded.invoke(bcPoint); } catch (ClassNotFoundException e) { throw new RuntimeException("encodePoint() failed", e); } catch (NoSuchMethodException e) { throw new RuntimeException("encodePoint() failed", e); } catch (IllegalAccessException e) { throw new RuntimeException("encodePoint() failed", e); } catch (InvocationTargetException e) { throw new RuntimeException("encodePoint() failed", e); } }