title: Difference between SHA256withRSA and SHA256 then RSA
body: <p>What is the difference between compute a signature with the following two methods?</p>
  
  <ol>
  <li>Compute a signature with <code>Signature.getInstance("SHA256withRSA")</code></li>
  <li>Compute SHA256 with <code>MessageDigest.getInstance("SHA-256")</code> and compute the digest with <code>Signature.getInstance("RSA");</code> to get the signature?</li>
  </ol>
  
  <p>If they are different, is there a way to modify the method 2 so that both methods give the same output?</p>
  
  <p>I tried the following code:</p>
  
  <pre><code>package mysha.mysha;
  import java.security.MessageDigest;
  import java.security.PrivateKey;
  import java.security.Security;
  import java.security.Signature;
  
  import org.bouncycastle.jce.provider.BouncyCastleProvider;
  
  public class MySHA256 {
  
      public static void main(String[] args) throws Exception {
          //compute SHA256 first
          Security.addProvider(new BouncyCastleProvider());
          String s = "1234";
          MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
          messageDigest.update(s.getBytes());
          byte[] outputDigest = messageDigest.digest();       
          //sign SHA256 with RSA
          PrivateKey privateKey = Share.loadPk8("D:/key.pk8");
          Signature rsaSignature = Signature.getInstance("RSA");
          rsaSignature.initSign(privateKey);
          rsaSignature.update(outputDigest);
          byte[] signed = rsaSignature.sign();
          System.out.println(bytesToHex(signed));
  
  
          //compute SHA256withRSA as a single step
          Signature rsaSha256Signature = Signature.getInstance("SHA256withRSA");
          rsaSha256Signature.initSign(privateKey);
          rsaSha256Signature.update(s.getBytes());
          byte[] signed2 = rsaSha256Signature.sign();
          System.out.println(bytesToHex(signed2));
      }
  
      public static String bytesToHex(byte[] bytes) {
          final char[] hexArray = "0123456789ABCDEF".toCharArray();
          char[] hexChars = new char[bytes.length * 2];
          for ( int j = 0; j &lt; bytes.length; j++ ) {
              int v = bytes[j] &amp; 0xFF;
              hexChars[j * 2] = hexArray[v &gt;&gt;&gt; 4];
              hexChars[j * 2 + 1] = hexArray[v &amp; 0x0F];
          }
          return new String(hexChars);
      }
  
  }
  </code></pre>
  
  <p>Nevertheless, the outputs are not the same.</p>
  
  <p>The following is the sample output with my test key:</p>
  
  <p>method 1: <code>61427B2A2CF1902A4B15F80156AEB09D8096BA1271F89F1919C78B18D0BABA08AA043A0037934B5AE3FC0EB7702898AC5AE96517AFD93433DF540353BCCE72A470CFA4B765D5835E7EA77743F3C4A0ABB11414B0141EF7ECCD2D5285A69728D0D0709C2537D6A772418A928B0E168F81C99B538FD25BDA7496AE8E185AC46F39</code></p>
  
  <p>method 2: <code>BA9039B75CA8A40DC9A7AED51E174E2B3365B2D6A1CF94DF70A00D898074A51FDD9973672DDE95CBAC39EBE4F3BA529C538ED0FF9F0A3F9A8CE203F1DFFA907DC508643906AA86DA54DFF8A90B00F5F116D13A53731384C1C5C9C4E75A3E41DAF88F74D2F1BCCF818764A4AB144A081B641C1C488AC8B194EB14BC9D1928E4EA</code></p>
  
  <p><strong>Update 1:</strong></p>
  
  <p>According to mkl's answer, I modify my code but still cannot get it right. Do I still miss something?</p>
  
  <pre><code>package mysha.mysha;
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.security.MessageDigest;
  import java.security.PrivateKey;
  import java.security.Security;
  import java.security.Signature;
  
  import org.bouncycastle.asn1.DEROutputStream;
  import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
  import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
  import org.bouncycastle.asn1.x509.DigestInfo;
  import org.bouncycastle.jce.provider.BouncyCastleProvider;
  
  public class MySHA256 { 
      public static void main(String[] args) throws Exception {
          //compute SHA256 first
          Security.addProvider(new BouncyCastleProvider());
          String s = "1234";
          MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
          messageDigest.update(s.getBytes());
          byte[] outputDigest = messageDigest.digest();
  
          AlgorithmIdentifier sha256Aid = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256, null);
          DigestInfo di = new DigestInfo(sha256Aid, outputDigest);
          //sign SHA256 with RSA
          PrivateKey privateKey = Share.loadPk8("D:/key.pk8");
          Signature rsaSignature = Signature.getInstance("RSA");
          rsaSignature.initSign(privateKey);
          rsaSignature.update(di.toASN1Primitive().getEncoded());
          byte[] signed = rsaSignature.sign();
          System.out.println("method 1: "+bytesToHex(signed));
  
  
          //compute SHA256withRSA as a single step
          Signature rsaSha256Signature = Signature.getInstance("SHA256withRSA");
          rsaSha256Signature.initSign(privateKey);
          rsaSha256Signature.update(s.getBytes());
          byte[] signed2 = rsaSha256Signature.sign();
          System.out.println("method 2: "+bytesToHex(signed2));
      }
      public static String bytesToHex(byte[] bytes) {
          final char[] hexArray = "0123456789ABCDEF".toCharArray();
          char[] hexChars = new char[bytes.length * 2];
          for ( int j = 0; j &lt; bytes.length; j++ ) {
              int v = bytes[j] &amp; 0xFF;
              hexChars[j * 2] = hexArray[v &gt;&gt;&gt; 4];
              hexChars[j * 2 + 1] = hexArray[v &amp; 0x0F];
          }
          return new String(hexChars);
      }
  }
  </code></pre>
  
  <p>method 1: 
  <code>675D868546777C5A9B5E74988E0CD41A46A929C1D0890B32B1FBE34F12D68F1FDB56E623294DB903F6AC60A2ADA61976B27C66056A16F5790A78168803AD2C685F9B4CF983C939305A9819CBA9D95441CD7214D40D06A98B4DDF9692A7D300DD51E808A6722A0D7C288DBD476DF4DEEBB3DAF41CFC0978F24424960F86F0284E</code></p>
  
  <p>method 2: 
  <code>BA9039B75CA8A40DC9A7AED51E174E2B3365B2D6A1CF94DF70A00D898074A51FDD9973672DDE95CBAC39EBE4F3BA529C538ED0FF9F0A3F9A8CE203F1DFFA907DC508643906AA86DA54DFF8A90B00F5F116D13A53731384C1C5C9C4E75A3E41DAF88F74D2F1BCCF818764A4AB144A081B641C1C488AC8B194EB14BC9D1928E4EA</code></p>