title: Keystore operation failed with RSA sign and verify
body: <p>I have difficulties to use RSA for signing and verifying. Below is part of my <code>RSA</code> class that I use. The methods <code>init()</code>, <code>privateKey()</code> and <code>publicKey()</code> work fine with <code>encrypt()</code> and <code>decrypt()</code> methods (last two not listed here), so I assume I made some mistake inside of my <code>sign()</code> method. Method <code>verify()</code> wasn't tested yet, because signing was unsuccessful, so I wasn't able to move further. Please take a look... </p>
  
  <hr>
  
  <p>My <code>RSA</code> class is:</p>
  
  <pre><code>class RSA
  {
      private final static String ANDROID_KEY_STORE = "AndroidKeyStore";
  
      public final static int ANY_PURPOSE = KeyProperties.PURPOSE_ENCRYPT | 
              KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_SIGN | 
              KeyProperties.PURPOSE_VERIFY;
  
      public final static long CENTURY = (100 * 365) + 24;
  </code></pre>
  
  <hr>
  
  <pre><code>    public enum KeySize
      {
          BIT_512  ( 512),
          BIT_768  ( 768),
          BIT_1024 (1024),
          BIT_2048 (2048),
          BIT_3072 (3072),
          BIT_4096 (4096);
  
          private int value;
  
          KeySize(int value)
          {
              this.value = value;
          }
  
          public int value()
          {
              return this.value;
          }
      }
  </code></pre>
  
  <hr>
  
  <pre><code>    public enum SignatureAlgorithm
      {
          MD5WithRSA        ("MD5WithRSA"),
          SHA1WithRSA       ("SHA1WithRSA"),
          SHA1WithRSA_PSS   ("SHA1WithRSA/PSS"),
          SHA224WithRSA     ("SHA224WithRSA"),
          SHA224WithRSA_PSS ("SHA224WithRSA/PSS"),
          SHA256WithRSA     ("SHA256WithRSA"),
          SHA256WithRSA_PSS ("SHA256WithRSA/PSS"),
          SHA384WithRSA     ("SHA384WithRSA"),
          SHA384WithRSA_PSS ("SHA384WithRSA/PSS"),
          SHA512WithRSA     ("SHA512WithRSA"),
          SHA512WithRSA_PSS ("SHA512WithRSA/PSS");
  
          private String value;
  
          SignatureAlgorithm(String value)
          {
              this.value = value;
          }
  
          public String value()
          {
              return this.value;
          }
      }
  </code></pre>
  
  <hr>
  
  <pre><code>    public static KeyPair init(final String alias, final RSA.KeySize keySize, 
                  final long validityDays, final Boolean reset)
              throws KeyStoreException, NoSuchAlgorithmException, CertificateException, 
              IOException, NoSuchProviderException, InvalidAlgorithmParameterException
      {
          KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
          keyStore.load(null);
          if (reset || (!keyStore.containsAlias(alias)))
          {
              final long now = java.lang.System.currentTimeMillis();
              KeyPairGenerator keyPairGenerator = KeyPairGenerator
                      .getInstance(KeyProperties.KEY_ALGORITHM_RSA, ANDROID_KEY_STORE);
              keyPairGenerator.initialize(
                      new KeyGenParameterSpec.Builder(alias, RSA.ANY_PURPOSE)
                      .setRandomizedEncryptionRequired(false)
                      .setDigests(
                              KeyProperties.DIGEST_NONE,   KeyProperties.DIGEST_MD5,
                              KeyProperties.DIGEST_SHA1,   KeyProperties.DIGEST_SHA224,
                              KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA384,
                              KeyProperties.DIGEST_SHA512)
                      .setKeySize(keySize.value())
                      .setEncryptionPaddings(
                              KeyProperties.ENCRYPTION_PADDING_NONE,
                              KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1,
                              KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
                      .setCertificateSubject(new X500Principal(
                              "CN=Android, O=Android Authority"))
                      .setCertificateSerialNumber(new BigInteger(256, new Random()))
                      .setCertificateNotBefore(new Date (now - (now % 1000L)))
                      .setCertificateNotAfter(new Date(((new Date(now - (now % 1000L)))
                              .getTime()) + (validityDays * 86400000L)))
                      .build());
              return keyPairGenerator.generateKeyPair();
          }
          else return null;
      }
  </code></pre>
  
  <hr>
  
  <pre><code>    public static PublicKey publicKey(final String alias)
              throws KeyStoreException, NoSuchAlgorithmException, CertificateException, 
              IOException, UnrecoverableEntryException
      {
          KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
          keyStore.load(null);
          return keyStore.getCertificate(alias).getPublicKey();
      }
  </code></pre>
  
  <hr>
  
  <pre><code>    public static PrivateKey privateKey(final String alias)
              throws KeyStoreException, NoSuchAlgorithmException, CertificateException, 
              IOException, UnrecoverableEntryException
      {
          KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
          keyStore.load(null);
          return (PrivateKey) keyStore.getKey(alias, null);
      }
  </code></pre>
  
  <hr>
  
  <pre><code>    public static byte[] sign(final String message, final String alias, 
                  final SignatureAlgorithm algorithm)
              throws KeyStoreException, NoSuchAlgorithmException, CertificateException, 
              IOException, UnrecoverableEntryException,
              InvalidKeyException, SignatureException
      {
          Signature instance = Signature.getInstance(algorithm.value());
          instance.initSign(privateKey(alias), new SecureRandom());
          instance.update(message.getBytes("UTF-8"));
          return instance.sign();
      }
  </code></pre>
  
  <hr>
  
  <pre><code>    public static Boolean verify(final String message, final byte[] signature, 
                  final String alias, final SignatureAlgorithm algorithm)
              throws KeyStoreException, NoSuchAlgorithmException, CertificateException, 
              IOException, UnrecoverableEntryException,
              InvalidKeyException, SignatureException
      {
          Signature instance = Signature.getInstance(algorithm.value());
          instance.initVerify(publicKey(alias));
          instance.update(message.getBytes("UTF-8"));
          return instance.verify(signature);
      }
  }
  </code></pre>
  
  <hr>
  
  <p>My <code>Hex</code> class is:</p>
  
  <pre><code>class Hex
  {
      private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
  
      public static String bytesToHexString(final byte[] bytes)
      {
          char[] hexChars = new char[2 * bytes.length];
          for (int i = 0; i &lt; bytes.length; i++)
          {
              int b = bytes[i] &amp; 0xFF;
              hexChars[2 * i] = hexArray[b &gt;&gt;&gt; 4];
              hexChars[2 * i + 1] = hexArray[b &amp; 0x0F];
          }
          return new String(hexChars);
      }
  }
  </code></pre>
  
  <hr>
  
  <p>My test code is:</p>
  
  <pre><code>try
  {
      RSA.init("RSA", RSA.KeySize.BIT_512, RSA.CENTURY, true);
  
      RSA.SignatureAlgorithm signatureAlgorithm = RSA.SignatureAlgorithm.SHA1WithRSA;
  
      byte[] x = RSA.sign("My message", "RSA", signatureAlgorithm);
      Log.d("RSA Test", "x: " + Hex.bytesToHexString(x));
  
      Boolean y = RSA.verify("My message", x, "RSA", signatureAlgorithm);
      Log.d("RSA Test", "y: " + (y? "True" : "False"));
  }
  catch (Exception e)
  {
      Log.d("RSA Test", "ERROR: " + e.toString());
  }
  </code></pre>
  
  <hr>
  
  <p>And the output is:</p>
  
  <blockquote>
    <p>ERROR: java.security.InvalidKeyException: Keystore operation failed</p>
  </blockquote>
  
  <p>Debugging shows that the error occur inside of my <code>RSA.sign()</code> method, when it calls <code>initSign()</code>.</p>
  
  <p>What is wrong in my code? </p>