Search code examples
androidweb-serviceshashandroid-ksoap2sha

Two different hash values even after entering same string in Android and .NET


I have a .NET SOAP web serviec(.asmx) for SHA-1 hashing to get Base64 hash string.

Here is my web service code:

 public class Service1 : System.Web.Services.WebService
  {
    [WebMethod]
    public string HashCode(string str)
    {
        string rethash = "";
        try
        {

            System.Security.Cryptography.SHA1 hash = System.Security.Cryptography.SHA1.Create();
            System.Text.ASCIIEncoding encoder = new System.Text.ASCIIEncoding();
            byte[] combined = encoder.GetBytes(str);
            hash.ComputeHash(combined);
            rethash = Convert.ToBase64String(hash.Hash);
        }
        catch (Exception ex)
        {
            string strerr = "Error in HashCode : " + ex.Message;
        }
        return rethash;
    }
}

Here hash returned for input string "abc" is

qZk+NkcGgWq6PiVxeFDCbJzQ2J0=

Now, Android code again using SHA-1 and Base64 is:

public class PaswordencodingActivity extends Activity 
   {
 private static final String soap_action = "http://tempuri.org/HashCode";
 private static final String method_name = "HashCode";
 private static final String namespace2 = "http://tempuri.org/";
 private static final String url2 = "http://10.0.2.2/checkhash/Service1.asmx"; 
    
String password="abc";
public final static int NO_OPTIONS = 0;
String hash;
    String result2;

   @Override
      public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
    
    final EditText pass=(EditText)findViewById(R.id.editText1);
    Button encode=(Button)findViewById(R.id.button1);
    
    encode.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v)  {
            // Perform action on click
            password=pass.getText().toString();
            if(password!=null){
            try {
    SHA1(password) ;
           } catch (NoSuchAlgorithmException e) {   
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
    // TODO Auto-generated catch block                                          
               e.printStackTrace();
    } catch (IOException e)
              {
    // TODO Auto-generated catch block
        e.printStackTrace();
        }
            }
            else{
    Toast.makeText(PaswordencodingActivity.this, "this is a negative onClick", Toast.LENGTH_LONG).show();
            }
               
         }
    });
    
}
private static String convertToHex(byte[] bytes) throws java.io.IOException 
 {       
      StringBuffer sb = new StringBuffer();
      String hex=null;
        for (int i = 0; i < bytes.length; i++) 
        {           
          hex=Base64.encodeToString(bytes, 0, bytes.length, NO_OPTIONS);
            if (hex.length() == 1) 
            {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }


 public  void SHA1(String text) 
      throws NoSuchAlgorithmException, IOException  
   { 
       MessageDigest md;
       md = MessageDigest.getInstance("SHA-1");
       byte[] sha1hash = new byte[40];
       md.update(text.getBytes("iso-8859-1"), 0, text.length());
       sha1hash = md.digest();
       hash=convertToHex(sha1hash);
       System.out.println("hash value is"+hash);
  try 
  {
        result2 = call3(hash);
} catch (XmlPullParserException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
 }
  
if(result2.equalsIgnoreCase(hash))
{
    System.out.println("success");
    
}

} 
 
public String call3(String hash) throws XmlPullParserException
    {
        String b="";     
        SoapObject request = new SoapObject(namespace2, method_name);                       
        request.addProperty("str",hash);
    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
     envelope.dotNet = true; 
     envelope.setOutputSoapObject(request);
        
     HttpTransportSE  android = new HttpTransportSE(url2);
         android.debug = true; 
  try 
 {
    
         android.call(soap_action, envelope);
         SoapPrimitive result = (SoapPrimitive)envelope.getResponse();
         Log.i("myapp",result.toString());
         System.out.println(" --- response ---- " + result); 
         b=result.toString();

 } catch (SocketException ex) { 
    ex.printStackTrace(); 
    } catch (Exception e) { 
    e.printStackTrace(); 
    } 
        
    return b;   
    
}

Android returned hash value is (from logcat for input String "abc")

11-24 13:56:35.179: INFO/myapp(578): 48a4yT8WPFCmkTxMSC9WaEtSxJI=

11-24 13:56:35.179: INFO/System.out(578): --- response ---- 48a4yT8WPFCmkTxMSC9WaEtSxJI=

Can someone tell what's going wrong in my code? Am I double hashing somewhere

Please help

Thanks


Solution

  • Check the encoding, make sure that the actual byte arrays that are used to compute the hash are equal. In .NET you use ASCII encoding and in Android iso-8859-1. This should not mater as the iso-8859-1 is natural extension of the ASCII encoding, but still, check the arrays. Also try using this function for SHA1 digest on Android:

     /**
       * Generates SHA-1 digest of the provided data.
       * 
       * @param data the data to digest
       * @return SHA-1 digest of the provided data.
       */
      public static byte[] sha1Digest(byte[] data) {
        MessageDigest mdSha1 = null;
        try {
          mdSha1 = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException e1) {
          Log.e(LOG_TAG, "Error initializing SHA1 message digest");
        }
        mdSha1.update(data);
        byte[] sha1hash = mdSha1.digest();
        return sha1hash;
      }