Question

I need implement login to .NET Soap Web Service. This Web Service has method

 AuthenticateUser(username, password)

and password should be encrypted with RSA public key. Below what I am trying to do:

 public static final String PUBLIC = "q/9CujExqL6rsMMO22WWIotoXDCw5KEmGQJqL9UJEfoErwZ9ZCm3OwMTSlAMSfoXEMA04Y1rhfYC3MtU/7dYEoREfsvOPGDBWanTKyMzv2otCfiURyQoghEdkhv3ipQQaaErT7lfBKobJsdqJlvxo4PCOUas2Z6YpoMYgthzTiM=";
    public static final String EXPONENT = "AQAB";

    public static PublicKey getPublicKey() throws Exception{
        byte[] modulusBytes = Base64.decode(PUBLIC, 0);
        byte[] exponentBytes = Base64.decode(EXPONENT,    0);

        BigInteger modulus = new BigInteger(1, (modulusBytes) );
        BigInteger exponent = new BigInteger(1, (exponentBytes));

        RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePublic(spec);
    }

    public static byte[] encrypt(Key publicKey, String s) throws Exception{
        byte[] byteData = s.getBytes("UTF-8");
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
        cipher.init(Cipher.ENCRYPT_MODE, publicKey); 
        byte[] encryptedData = cipher.doFinal(byteData);
        return encryptedData;
    }

    public static String arrayAsString (byte [] array){
        String p = "";
        for (int i = 0; i < array.length; i++) {
            p +=  unsignedToBytes(array[i]);
            if (i < array.length - 1)
                p+= ",";
        }
        return p;
    }

    public static int unsignedToBytes(byte b) {
        return b & 0xFF;
    }

   public static void main(String[] args){
        PublicKey publicKey = getPublicKey();
        byte [] encrypted = encode(publicKey, "passwordHere");
        String pass = arrayAsString(encrypted);
        webservice.AuthenticateUser("testAdmin", pass); 
   }

I also have .NET code from Web Service side

    private static string publicKey = "<RSAKeyValue><Modulus>q/9CujExqL6rsMMO22WWIotoXDCw5KEmGQJqL9UJEfoErwZ9ZCm3OwMTSlAMSfoXEMA04Y1rhfYC3MtU/7dYEoREfsvOPGDBWanTKyMzv2otCfiURyQoghEdkhv3ipQQaaErT7lfBKobJsdqJlvxo4PCOUas2Z6YpoMYgthzTiM=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
    private static UnicodeEncoding _encoder = new UnicodeEncoding();

    public static string Encrypt(string data)
    {
        var rsa = new RSACryptoServiceProvider();
        rsa.FromXmlString(publicKey);
        var dataToEncrypt = _encoder.GetBytes(data);
        var encryptedByteArray = rsa.Encrypt(dataToEncrypt, false).ToArray();
        var length = encryptedByteArray.Count();
        var item = 0;
        var sb = new StringBuilder();
        foreach (var x in encryptedByteArray)
        {
            item++;
            sb.Append(x);

            if (item < length)
                sb.Append(",");
        }

        return sb.ToString();
    }



    public static string Decrypt(string data)
    {
        var rsa = new RSACryptoServiceProvider();
        var dataArray = data.Split(new char[] { ',' });
        byte[] dataByte = new byte[dataArray.Length];
        for (int i = 0; i < dataArray.Length; i++)
        {
            dataByte[i] = Convert.ToByte(dataArray[i]);
        }

        rsa.FromXmlString(privateKey);
        var decryptedByte = rsa.Decrypt(dataByte, false);
        return _encoder.GetString(decryptedByte);
    }

Is somebody have any idea what I am doing wrong? Why Web Service always returns me AuthenticateUserResponse{AuthenticateUserResult=false; }

Was it helpful?

Solution

I think the problem here is may be to do with text encoding, rather than the encryption/decryption process itself. On the Java side, you're encrypting the UTF-8 encoded password, whereas on the .NET side, it's using UnicodeEncoding which is UTF-16. Try using UTF-16 on the Java side before encryption instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top