title: RSA signature verification given public exponent and modulus
body: <p>Trying to code signature verification using Sun JCE with test vectors from the CAVP program.</p>
  
  <p>i'm given public key exponent, and modulus, as well as the message and signature.  I do the following:</p>
  
  <pre><code>    private static boolean verifySignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes, int saltlen)  throws Exception
      {
              Signature sig = Signature.getInstance(algo);
              KeyFactory keyMaker = KeyFactory.getInstance("RSA");
              RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
                              new BigInteger(modulus),
                              new BigInteger(exponent));
  
              RSAPublicKey pubKey = (RSAPublicKey)keyMaker.generatePublic(pubKeySpec);
  
              System.out.println("algorithm is " + algo);
              sig.initVerify(pubKey);
              Utils.outputValue("n", modulus, modulus.length, System.out, false);
              Utils.outputValue("e", exponent, exponent.length, System.out, false);
              Utils.outputValue("Msg", message, message.length, System.out, false);
              Utils.outputValue("S", sigBytes, sigBytes.length, System.out, false);
              BigInteger Nvalue = pubKey.getPublicExponent();
              Utils.outputValue("key value of n", Nvalue.toByteArray(), System.out, false);
              BigInteger Evalue=pubKey.getModulus();
              Utils.outputValue("key value of e", Evalue.toByteArray(), System.out, false);
              sig.update(message);
              if(sig.verify(sigBytes))
                      oPS.println("Result = P");
              else
                      oPS.println("Result = F");
  </code></pre>
  
  <p>.
  .
  .</p>
  
  <p>The algo is something like "SHA1withRSA", and i build the public key as shown.  When i list the resulting modulus and exponent from the key itself, they have become reversed. </p>
  
  <p>n = 009de541c71a95389d9e8619ea1d6e2c69ed6c703701e518351676022ab98395d6b35a38b024f92bce6dd1c5be9d51dffd1687d19dceee73f2c73e4436b955231255f6e3e360ba84462311e10e65932fe069bed2d42c5bf2f88141828bdad3796184870cb8cf3019da264e56b39eccf7224d43a1b98d788b40a4042aac790e946f
  e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
  Msg = 64b13df4b008ccccd5ce146018481c2568bbe2b93ec658d1c7f4ad734592cd65b3be2be5a7c1be9a7d9f49cbb2ece0cf8ee0a8c406aede84e0121bd51829d6e083862ae5b282d92c19d3923f70616f565a55c2134572116f91a85ff5f4e6ad2e1d31c15c97f3266af19574241c4fd2a4143fb80cc2b9fa7b22df0239a1715c35
  S = 5b4458f6aeff91c4699ee9bdf8757987fb8db229814a2992945ac53bcf19b9179e53cfed258726d205107ac000d41e570fe8c4fb321fc9b4b5469c60cd20032195f314ba6e6b0b30a51c9834242daa1ce525ec90380106568e782ea164baeda5d884defe6e720e9dd63618b823412445e17f991a6daa21bd62bdc73d7d8a20e5
  key value of n = 03
  key value of e = 009de541c71a95389d9e8619ea1d6e2c69ed6c703701e518351676022ab98395d6b35a38b024f92bce6dd1c5be9d51dffd1687d19dceee73f2c73e4436b955231255f6e3e360ba84462311e10e65932fe069bed2d42c5bf2f88141828bdad3796184870cb8cf3019da264e56b39eccf7224d43a1b98d788b40a4042aac790e946f</p>
  
  <p>Some of these tests are supposed to fail, but some should succeed.  None verify correctly...  Any thought?  Thanks.   </p>
  
  <p>Application is below, followed by one set of sample input.</p>
  
  <pre><code>package cavp.rsa;
  
  
  import cavp.*;
  
  import java.io.*;
  
  import java.security.KeyFactory;
  import java.security.SecureRandom;
  import java.security.Signature;
  import java.security.interfaces.RSAPublicKey;
  import java.security.spec.RSAPublicKeySpec;
  import java.security.PublicKey;
  
  import java.util.Date;
  
  import java.math.BigInteger;
  
  public class RSASigVerify
  {
          private static boolean verboseFlag=false;
  
          public static void main(String[] args) throws Exception
          {
                  String requestFile;
                  String responseFile;
  
                  int saltLen=-1;
                  int argstart=0;
  
                  if(args.length &lt; 2)
                          throw new Exception("missing parameters");
                  if(args.length == 3) {
                          if(args[0].equals("-saltlen")) {
                                  saltLen=Integer.parseInt(args[1]);
                                  if(saltLen &lt; 0)
                                          throw new Exception("bad -saltlen parameter ");
                                  argstart=2;
                          } else {
                                  if(args[0].equals("-x931")) {
                                          saltLen=-2;
                                          argstart=1;
                                  }
                  } else {
                          if(args.length &gt; 3)
                                  throw new Exception("invalid invocation");
                  }
                  requestFile=args[argstart];
                  responseFile=args[argstart+1];
                  if(processFile(requestFile, responseFile, saltLen))
                          System.out.println("Failed to process file " + requestFile);
                  else
                          System.out.println("Processing complete for " + requestFile);
          }
  
          private static boolean processFile(String rqfn, String rspfn, int saltLen) throws Exception
          {
                  File inFile = new File(rqfn), outFile = new File(rspfn);
  
                  if(!inFile.exists() || !inFile.isFile() || !inFile.canRead()) {
                          System.out.println("Bad input File " + rqfn);
                          return true;
                  }
                  FileReader inFR = new FileReader(inFile);
                  BufferedReader inBR = new BufferedReader(inFR);
                  PrintStream outPS = new PrintStream(outFile);
  
                  String input, keyword, value, digestType=null;
                  int p, v, q, i, lnum=0;
                  byte[] Msg=null, nBytes=null, eBytes=null, sigBytes=null;
                  boolean msgFound=false, nFound=false, eFound=false, sigFound=false;
  
  
                  try {
                          while((input = inBR.readLine()) != null ) {
                                  lnum++;
                                  if((p = input.indexOf('=')) &lt; 0) {
                                          outPS.println(input);
                                          continue;
                                  }
                                  if(input.charAt(p-1) == ' ')
                                          keyword=input.substring(0,p-1);
                                  else
                                          keyword=input.substring(0, p);
                                  p++;
                                  for(i=p; i&lt;input.length(); i++) {
                                          if(input.charAt(i) == ' ')
                                                  p++;
                                          else
                                                  break;
                                  }
                                  if((v = input.indexOf('\n')) &gt; 0) {
                                          for(q=v-1; q&gt;p+1; q--) {
                                                  if(input.charAt(q) != ' ')
                                                          break;
                                          }
                                  } else {
                                          if((v = input.indexOf(' ', p)) &gt; 0) {
                                                  q=v-1;
                                          } else {
                                                  q=input.length();
                                          }
                                  }
  
                                  value=input.substring(p,q);
                                  if(keyword.indexOf("n") &gt;= 0) {
                                          nBytes=Utils.hexStringToByteArray(value);
                                          if(nBytes.length &lt;= 0) {
                                                  System.out.println("bad value for modulus");
                                                  return true;
                                          }
                                          nFound=true;
                                  } else {
                                          if(keyword.equals("e")) {
                                                  eBytes=Utils.hexStringToByteArray(value);
                                                  if(eBytes.length &lt;= 0) {
                                                          System.out.println("bad value for private exponent");
                                                          return true;
                                                  }
                                                  eFound=true;
  
                                          } else {
                                                  if(keyword.equals("SHAAlg")) {
                                                          if(!value.equals("SHA1") &amp;&amp; !value.equals("SHA224") &amp;&amp; !value.equals("SHA256") &amp;&amp; !value.equals("SHA384") &amp;&amp;
                                                                          !value.equals("SHA512")) {
                                                                  System.out.println("Bad SHAAlg parameter " + input);
                                                                  return true;
                                                          }
                                                          digestType=value + "withRSA";
                                                  } else {
                                                          if(keyword.equals("Msg")) {
                                                                  if(msgFound) {
                                                                          System.out.println("more than one Msg found");
                                                                          return true;
                                                                  } else
                                                                          msgFound=true;
                                                                  String tempMsg;
                                                                  if((value.length() &amp; 0x01) != 0)  {
                                                                          tempMsg="0" + value;
                                                                  } else {
                                                                          tempMsg=value;
                                                                  }
                                                                  Msg=Utils.hexStringToByteArray(tempMsg);
                                                                  if(Msg.length &lt;= 0) {
                                                                          System.out.println("bad Msg parameter");
                                                                          return true;
                                                                  }
                                                          } else {
                                                                  if(keyword.equals("S")) {
                                                                          sigBytes=Utils.hexStringToByteArray(value);
                                                                          if(sigBytes.length &lt;= 0) {
                                                                                  System.out.println("bad signature parameter");
                                                                                  return true;
                                                                          }
                                                                          sigFound=true;
                                                                  } else {
                                                                          if(keyword.equals("Result")) {
                                                                                  continue;
                                                                          }
                                                                  }
                                                          }
                                                  }
  
  
                                          }
                                  }
                                  outPS.println(input);
                                  if(digestType != null &amp;&amp; msgFound &amp;&amp; nFound &amp;&amp; eFound &amp;&amp; sigFound) {
                                          if(verifySignature(digestType, outPS, Msg, nBytes, eBytes, sigBytes, saltLen)) {
                                                  throw new Exception("error in digest generator");
                                          }
                                          msgFound=false;
                                          eFound=false;
                                          sigFound=false;
                                  }
                          }
                  } catch( FileNotFoundException e) {
                          System.out.println("error processing file");
                  }
                  inFR.close();
                  outPS.close();
                  return false;
          }
  
          private static boolean verifySignature(String algo, PrintStream oPS, byte[] message, byte[] modulus, byte[] exponent, byte[] sigBytes, int saltlen)  throws Exception
          {
                  // yet to implement saltLen == -2 for X9.31 padding
                  //                  saltLen &gt;= 0 for PSS Signatures
  
                  Signature sig = Signature.getInstance(algo);
                  KeyFactory keyMaker = KeyFactory.getInstance("RSA");
                  RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
                                  new BigInteger(modulus),
                                  new BigInteger(exponent));
  
  
                  RSAPublicKey pubKey = (RSAPublicKey)keyMaker.generatePublic(pubKeySpec);
  
                  System.out.println("algorithm is " + algo);
                  sig.initVerify(pubKey);
                  sig.update(message);
                  if(sig.verify(sigBytes))
                          oPS.println("Result = P");
                  else
                          oPS.println("Result = F");
                  return false;
          }
  }
  </code></pre>
  
  <p>The following is one vector from the input:</p>
  
  <pre><code># CAVS 11.5
  # "SigVer PKCS#1 Ver 1.5" information for
  # Mod sizes selected: 1024 2048
  # SHA Algorithm selected:SHA1 SHA256
  # Generated on Mon Nov 28 14:03:58 2011
  [mod = 1024]
  n = 9de541c71a95389d9e8619ea1d6e2c69ed6c703701e518351676022ab98395d6b35a38b024f92bce6dd1c5be9d&gt;51dffd1687d19dceee73f2c73e4436b955231255f6e3e360ba84462311e10e65932fe069bed2d42c5bf2f88141&gt;828bdad3796184870cb8cf3019da264e56b39eccf7224d43a1b98d788b40a4042aac790e946f
  SHAAlg = SHA1
  e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&gt;000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&gt;0000000000000000000000000000000000000000000000000000000000000000000000000003
  Msg = 64b13df4b008ccccd5ce146018481c2568bbe2b93ec658d1c7f4ad734592cd65b3be2be5a7c1be9a7d9f49cbb2&gt;ece0cf8ee0a8c406aede84e0121bd51829d6e083862ae5b282d92c19d3923f70616f565a55c2134572116f91a8&gt;5ff5f4e6ad2e1d31c15c97f3266af19574241c4fd2a4143fb80cc2b9fa7b22df0239a1715c35
  S = 5b4458f6aeff91c4699ee9bdf8757987fb8db229814a2992945ac53bcf19b9179e53cfed258726d205107ac000&gt;d41e570fe8c4fb321fc9b4b5469c60cd20032195f314ba6e6b0b30a51c9834242daa1ce525ec90380106568e78&gt;2ea164baeda5d884defe6e720e9dd63618b823412445e17f991a6daa21bd62bdc73d7d8a20e5*
  </code></pre>
  
  <p>Here is a vector file which should Pass:</p>
  
  <pre><code># CAVS 11.5
  # "SigVer PKCS#1 Ver 1.5" information for 
  # Mod sizes selected: 1024 2048
  # SHA Algorithm selected:SHA1 SHA256
  # Generated on Mon Nov 28 14:03:58 2011
  
  [mod = 1024]
  
  n = 9de541c71a95389d9e8619ea1d6e2c69ed6c703701e518351676022ab98395d6b35a38b024f92bce6dd1c5be9d51dffd1687d19dceee73f2c73e4436b955231255f6e3e360ba84462311e10e65932fe069bed2d42c5bf2f88141828bdad3796184870cb8cf3019da264e56b39eccf7224d43a1b98d788b40a4042aac790e946f
  
  SHAAlg = SHA1
  e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
  Msg = fe196459e8232a9f94e8c93d88ddae7d38be7a10e2dd03ffb7bb9be43bd59659eec006b12c78c9e652f6c6d3220073a369459b8adea95eb34ede7979f634c7d931b208275365e201d4f82582b18553b70fab605721e1b6ae4d097cdb8a49183b0d16f22524917bd862176fb1fc1357a2731751df732c13dafc662e72bfbb9067
  S = 94af4ce7f323d1bf4904a673d2884e30a55a108c44e4eb2bfc0a0f061f46fefe23fe74c760e947bd1fbf1bb1a30d66b3d7dccfb425d3a6551dd444f90d4f06c3e0da6dc3c7a45e062b08d24553f0091acae47ffaae495e13da66308dd9e0be87e2b960ab823f83e55815b66a1076ab238cc3883cbf7312521d0988214bb07d96
  </code></pre>