title: Retrieve ECC Public Key from Base64 encoded string
body: <p>I've been trying to create an instance of <code>java.security.PublicKey</code> using a Base64 encoded ECC public key.</p>
  
  <h3>MainActivity.java</h3>
  
  <pre><code>@Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
  
      try {
          byte[] data = decodePublicKey("AsIAEFjzIcX+Kvhe8AmLoGUc8aYAEAwf5ecREGZ2u4RLxQuav/A=");
          PublicKey publicKey = loadPublicKey("secp128r1", data);
  
          Log.d(TAG, publicKey.toString());
      } catch (SQLException | IOException | GeneralSecurityException e) {
          Log.e(TAG, e.getMessage(), e);
      }
  }
  
  private byte[] decodePublicKey(String s) throws UnsupportedEncodingException {
      return Base64.decode(s, Base64.DEFAULT);
  }
  
  public PublicKey loadPublicKey(String curve, byte[] data)
          throws SQLException, IOException, GeneralSecurityException {
      Log.d(TAG, Arrays.toString(data));
      // [2, -62, 0, 16, 88, -13, 33, -59, -2, 42, -8, 94, -16, 9, -117, -96, 101, 28, -15, -90, 0, 16, 12, 31, -27, -25, 17, 16, 102, 118, -69, -124, 75, -59, 11, -102, -65, -16]
      Log.d(TAG, "Length :" + String.valueOf(data.length));
  
      KeyFactory factory = KeyFactory.getInstance("EC", "SC");
      ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curve);
      ECCurve eccCurve = spec.getCurve();
      Log.d(TAG, "Curve: " + curve);
  
      EllipticCurve ellipticCurve = EC5Util.convertCurve(eccCurve, spec.getSeed());
  
      // decoding point fails, 
      // line no 66.
      ECPoint point = ECPointUtil.decodePoint(ellipticCurve, data);
      ECParameterSpec params = EC5Util.convertSpec(ellipticCurve, spec);
  
      ECPublicKeySpec keySpec = new ECPublicKeySpec(point, params);
      return factory.generatePublic(keySpec);
  }
  </code></pre>
  
  <h3>Logcat:</h3>
  
  <pre><code>Process: com.example.eccdemo, PID: 21151
  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.eccdemo/com.example.eccdemo.MainActivity}: java.lang.IllegalArgumentException: Incorrect length for compressed encoding
          at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2329)
          at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389)
          at android.app.ActivityThread.access$900(ActivityThread.java:147)
          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1296)
          at android.os.Handler.dispatchMessage(Handler.java:102)
          at android.os.Looper.loop(Looper.java:135)
          at android.app.ActivityThread.main(ActivityThread.java:5254)
          at java.lang.reflect.Method.invoke(Native Method)
          at java.lang.reflect.Method.invoke(Method.java:372)
          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
   Caused by: java.lang.IllegalArgumentException: Incorrect length for compressed encoding
          at org.spongycastle.math.ec.ECCurve.decodePoint(ECCurve.java:349)
          at org.spongycastle.jce.ECPointUtil.decodePoint(ECPointUtil.java:52)
          at com.example.eccdemo.MainActivity.loadPublicKey(MainActivity.java:66)
          at com.example.eccdemo.MainActivity.onCreate(MainActivity.java:45)
          at android.app.Activity.performCreate(Activity.java:5933)
          at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
          at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2282)
          at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389)
          at android.app.ActivityThread.access$900(ActivityThread.java:147)
          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1296)
          at android.os.Handler.dispatchMessage(Handler.java:102)
          at android.os.Looper.loop(Looper.java:135)
          at android.app.ActivityThread.main(ActivityThread.java:5254)
          at java.lang.reflect.Method.invoke(Native Method)
          at java.lang.reflect.Method.invoke(Method.java:372)
          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
  </code></pre>
  
  <h2>Further Inspection:</h2>
  
  <p>In Logcat, upon printing the decoded bytes, they actually differ from the one on the server:</p>
  
  <pre><code>    Log.d(TAG, Arrays.toString(data));
      [2, -62, 0, 16, 88, -13, 33, -59, -2, 42, -8, 94, -16, 9, -117, -96, 101, 28, -15, -90, 0, 16, 12, 31, -27, -25, 17, 16, 102, 118, -69, -124, 75, -59, 11, -102, -65, -16]
  </code></pre>
  
  <p>In python console:</p>
  
  <pre><code>In [131]: [_ for _ in ap.public_key.tobytes()]
  Out[131]: [2, 194, 0, 16, 88, 243, 33, 197, 254, 42, 248, 94, 240, 9, 139, 160, 101, 28, 241, 166, 0, 16, 12, 31, 229, 231, 17, 16, 102, 118, 187, 132, 75, 197, 11, 154, 191, 240]
  </code></pre>
  
  <p>It would be great if someone can explain the reason to this anomaly, and also help me out on the small snippet to get <code>PublicKey</code> instance from the String.</p>
  
  <p>References:</p>
  
  <ul>
  <li><p><a href="http://www.programcreek.com/java-api-examples/index.php?api=org.bouncycastle.asn1.ASN1InputStream" rel="nofollow">http://www.programcreek.com/java-api-examples/index.php?api=org.bouncycastle.asn1.ASN1InputStream</a></p></li>
  <li><p><a href="http://www.bouncycastle.org/wiki/display/JA1/Elliptic+Curve+Key+Pair+Generation+and+Key+Factories" rel="nofollow">http://www.bouncycastle.org/wiki/display/JA1/Elliptic+Curve+Key+Pair+Generation+and+Key+Factories</a></p></li>
  </ul>
  
  <p>Thanks in advance!!</p>
  
  <h2>Update:</h2>
  
  <p>When trying to load ASN1Primitive using the line below, it throws the following exception:</p>
  
  <pre><code>ASN1Primitive.fromByteArray(data);
  </code></pre>
  
  <p>Exception:</p>
  
  <pre><code>java.io.IOException: DER length more than 4 bytes: 66
          at org.spongycastle.asn1.ASN1InputStream.readLength(ASN1InputStream.java:347)
          at org.spongycastle.asn1.ASN1InputStream.readLength(ASN1InputStream.java:112)
          at org.spongycastle.asn1.ASN1InputStream.readObject(ASN1InputStream.java:237)
          at org.spongycastle.asn1.ASN1Primitive.fromByteArray(ASN1Primitive.java:30)
          at com.example.eccdemo.MainActivity.onCreate(MainActivity.java:48)
          at android.app.Activity.performCreate(Activity.java:5933)
          at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
          at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2282)
          at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389)
          at android.app.ActivityThread.access$900(ActivityThread.java:147)
          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1296)
          at android.os.Handler.dispatchMessage(Handler.java:102)
          at android.os.Looper.loop(Looper.java:135)
          at android.app.ActivityThread.main(ActivityThread.java:5254)
          at java.lang.reflect.Method.invoke(Native Method)
          at java.lang.reflect.Method.invoke(Method.java:372)
          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
  </code></pre>