views:

2071

answers:

2

I'm working on an useragent that logs into teamcity and I'm trying to move the password encryption from js to c#.

this is the javascript

the section called rsa.js and encrypt.js are important. They make a function call with

rsa.setPublic(publicKey,"10001");

The exponent looks like its a hex number x10001 which is 65537 base10 as far as I can tell

here is teamcity's demo site

Note the account below does not belong to teamcity's demo site

This test validates if the encrypted text is equal to the clear text being encrypted with the public key.

[Test]
public void should_be_able_to_encode_a_string() {
    string public_key = "00b46e5cd2f8671ebf2705fd9553137da082b2dd3dbfa06f254cdfeb260fb21bc2c37a882de2924d7dd4c61eb81368216dfea7df718488b000afe7120f3bbbe5b276ac7f2dd52bd28445a9be065bd19dab1f177e0acc035be4c6ccd623c1de7724356f9d6e0b703d01583ebc4467d8454a97928b5c6d0ba3f09f2f8131cc7095d9";
    string expected = "1ae1d5b745776f72172b5753665f5df65fc4baec5dd4ea17d43e11d07f10425b3e3164b0c2ba611c72559dc2b00149f4ff5a9649b1d050ca6a5e2ec5d96b787212874ab5790922528a9d7523ab4fe3a002e8f3b66cab6e935ad900805cf1a98dc6fcb5293c7f808917fd9015ba3fea1d59e533f2bdd10471732cccd87eda71b1";
    string data = "scott.cowan";
    string actual = new EncryptionHelper().Encrypt(public_key, data);
    Assert.AreEqual(expected,actual);
}

so far the implementation looks like

public string Encrypt(string public_key, string data)
{
    rsa = new RSACryptoServiceProvider(); 
    rsa.FromXmlString(String.Format("<RSAKeyValue>{0}</RSAKeyValue>",public_key));
    byte[] plainbytes = System.Text.Encoding.UTF8.GetBytes(data);
    byte[] cipherbytes = rsa.Encrypt(plainbytes,false);
    return Convert.ToBase64String(cipherbytes);
}

but this complains with

System.Security.Cryptography.CryptographicException
Message: Input string does not contain a valid encoding of the 'RSA' 'Modulus' parameter.

Thank you any help will make this a very merry christmas

Edit: looks like my test is flawed since a different encryptedPassword is generated with each seeded time

Answer: I turned on guest access, that bypasses this problem, but I'd still like to solve it

+2  A: 

You RSAKeyValue XML is malformed, the correct format is here http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue

your function should probably look like (assuming that public_key and exponent are octet strings...)

public string Encrypt(string public_key,string exponent, string data)
{
    rsa = new RSACryptoServiceProvider(); 
    rsa.FromXmlString(String.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",public_key,exponent));
    byte[] plainbytes = System.Text.Encoding.UTF8.GetBytes(data);
    byte[] cipherbytes = rsa.Encrypt(plainbytes,false);
    return Convert.ToBase64String(cipherbytes);
}

In your case your exponent is 10001.

since in your case it looks like you do not have octet strings

public string Encrypt(string public_keyHex,uint exp,string data)
{
    byte[] bytes = new byte[public_keyHex.Length / 2];
    for (int i = 0; i < public_keyHex.Length-1; i+=2)
    {
        bytes[i / 2] = byte.Parse(public_keyHex.Substring(i, 2),System.Globalization.NumberStyles.HexNumber);
    }
    string public_key=Convert.ToBase64String(bytes)
    return Encrypt(public_key,Convert.ToBase64String(BitConverter.GetBytes(exp)),data);
}

I hope that helps, I haven't tested it yet. i will when i get home today.

Cipher
ok this compiles, once the result is converted to hex it didn't match up to the exponents I was using. They use x10001 which is 65537 base10 but that doesn't give the expected result. the encoded text is about the same length as the expected though
Scott Cowan