title: Using SHA1 and RSA with java.security.Signature vs. MessageDigest and Cipher
body: <p>I'm trying to understand what the Java <em>java.security.Signature</em> class does. If I compute an SHA1 message digest, and then encrypt that digest using RSA, I get a different result to asking the <em>Signature</em> class to sign the same thing:</p>
  
  <pre><code>// Generate new key
  KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
  PrivateKey privateKey = keyPair.getPrivate();
  String plaintext = "This is the message being signed";
  
  // Compute signature
  Signature instance = Signature.getInstance("SHA1withRSA");
  instance.initSign(privateKey);
  instance.update((plaintext).getBytes());
  byte[] signature = instance.sign();
  
  // Compute digest
  MessageDigest sha1 = MessageDigest.getInstance("SHA1");
  byte[] digest = sha1.digest((plaintext).getBytes());
  
  // Encrypt digest
  Cipher cipher = Cipher.getInstance("RSA");
  cipher.init(Cipher.ENCRYPT_MODE, privateKey);
  byte[] cipherText = cipher.doFinal(digest);
  
  // Display results
  System.out.println("Input data: " + plaintext);
  System.out.println("Digest: " + bytes2String(digest));
  System.out.println("Cipher text: " + bytes2String(cipherText));
  System.out.println("Signature: " + bytes2String(signature));
  </code></pre>
  
  <p>Results in (for example):</p>
  
  <blockquote>
    <p>Input data: This is the message being signed<br>
    Digest: 62b0a9ef15461c82766fb5bdaae9edbe4ac2e067<br>
    Cipher text: 057dc0d2f7f54acc95d3cf5cba9f944619394711003bdd12...<br>
    Signature: 7177c74bbbb871cc0af92e30d2808ebae146f25d3fd8ba1622...</p>
  </blockquote>
  
  <p>I must have a fundamental misunderstanding of what <em>Signature</em> is doing - I've traced through it, and it appears to be calling update on a <em>MessageDigest</em> object, with the algorithm set to SHA1 as I would expect, then getting the digest, then doing the encryption. What's making the results differ?</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>Leonidas made me check whether the signature scheme is supposed to do what I think it does. There are two types of signature defined in the <a href="http://www.apps.ietf.org/rfc/rfc3447.html" rel="noreferrer">RFC</a>:</p>
  
  <ul>
  <li><a href="http://www.apps.ietf.org/rfc/rfc3447.html#sec-9.2" rel="noreferrer">RSASSA-PKCS1-v1_5</a></li>
  <li><a href="http://www.apps.ietf.org/rfc/rfc3447.html#sec-9.1" rel="noreferrer">RSASSA-PSS</a></li>
  </ul>
  
  <p>The <a href="http://www.apps.ietf.org/rfc/rfc3447.html#sec-9.2" rel="noreferrer">first of these</a> (PKCS1) is the one I describe above. It uses a hash function to create a digest, and then encrypts the result with a private key.</p>
  
  <p>The <a href="http://www.apps.ietf.org/rfc/rfc3447.html#sec-9.1" rel="noreferrer">second algorithm</a> uses a random salt value, and is more secure but non-deterministic. The signature produced from the code above does not change if the same key is used repeatedly, so I don't think it can be PSS.</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>Here's the <code>bytes2string</code> method I was using:</p>
  
  <pre><code>private static String bytes2String(byte[] bytes) {
      StringBuilder string = new StringBuilder();
      for (byte b : bytes) {
          String hexString = Integer.toHexString(0x00FF &amp; b);
          string.append(hexString.length() == 1 ? "0" + hexString : hexString);
      }
      return string.toString();
  }
  </code></pre>