public PublicKey decompressPublicKey()

in src/main/java/com/amazonaws/encryptionsdk/internal/TrailingSignatureAlgorithm.java [135:178]


    public PublicKey decompressPublicKey(final byte[] decodedKey) {
      notNull(decodedKey, "decodedKey is required");

      final BigInteger x = new BigInteger(1, Arrays.copyOfRange(decodedKey, 1, decodedKey.length));

      final byte compressedY = decodedKey[0];
      final BigInteger yOrder;

      if (compressedY == TWO.byteValue()) {
        yOrder = ZERO;
      } else if (compressedY == THREE.byteValue()) {
        yOrder = ONE;
      } else {
        throw new IllegalArgumentException("Compressed y value was invalid");
      }

      final BigInteger p = ((ECFieldFp) ecParameterSpec.getCurve().getField()).getP();
      final BigInteger a = ecParameterSpec.getCurve().getA();
      final BigInteger b = ecParameterSpec.getCurve().getB();

      // alpha must be equal to y^2, this is validated below
      final BigInteger alpha = x.modPow(THREE, p).add(a.multiply(x).mod(p)).add(b).mod(p);

      final BigInteger beta;
      if (p.mod(FOUR).equals(THREE)) {
        beta = alpha.modPow(p.add(ONE).divide(FOUR), p);
      } else {
        throw new IllegalArgumentException("Curve not supported at this time");
      }

      final BigInteger y = beta.mod(TWO).equals(yOrder) ? beta : p.subtract(beta);

      // Validate that Y is a root of Y^2 to prevent invalid point attacks
      if (!alpha.equals(y.modPow(TWO, p))) {
        throw new IllegalArgumentException("Y was invalid");
      }

      try {
        return KeyFactory.getInstance(ELLIPTIC_CURVE_ALGORITHM)
            .generatePublic(new ECPublicKeySpec(new ECPoint(x, y), ecParameterSpec));
      } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
        throw new IllegalStateException("Invalid algorithm", e);
      }
    }