Search code examples
c#gitencryptionsshopenssh

Weak Key error on Github, with 4096 RSAkey generated with C#


I am generating a RSA KEY with 4096 bits according to RFC4716 (Or at least I thought so) using C# and the standard cryptography library, however git hub says I have a key with the wrong size, returning the following error when I try to add it to the keys associated to my account.

Key is weak. GitHub recommends using ssh-keygen to generate a RSA key of at least 2048 bits.

This is the code to generate the key:

public static void GenerateKeys()
    {
        // Create the CspParameters object and set the key container   
        // name used to store the RSA key pair.  
        CspParameters cp = new CspParameters();
        //cp.KeyContainerName = ContainerName;

        CspKeyContainerInfo info = new CspKeyContainerInfo(cp);
        //string filename = info.UniqueKeyContainerName;

        // Create a new instance of RSACryptoServiceProvider that accesses  
        // the key container MyKeyContainerName.  
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(4096, cp);
        var test = rsa.KeySize;

        using (StreamWriter privateKeyWriter = new StreamWriter(GitStandard.PrivateSSHKeyPath))
        {
            ExportPrivateKey(rsa, privateKeyWriter);
        }

        using (StreamWriter publicKeyWriter = new StreamWriter(GitStandard.PublicSSHKeyPath))
        {

            ExportPublicKeyOpenSSH(rsa, publicKeyWriter);
        }
    }

The method ExportPublicKeyOpenSSH is a small modification of the code found in this thread with answers on how to convert the key to RFC4716, the only thing I do differently is to add a zero (0) before the modulus is converted.

private static void ExportPublicKeyOpenSSH(RSACryptoServiceProvider csp, TextWriter outputStream)
        {
            var parameters = csp.ExportParameters(false);


            byte[] sshrsa_bytes = Encoding.Default.GetBytes("ssh-rsa");
            //initializing modulus array
            byte[] n = new Byte[parameters.Modulus.Length + 1];
            //adding initial zero before modulus to conform with OpenSSH
            n[0] = 0;
            System.Buffer.BlockCopy(parameters.Modulus, 0, n, 1, parameters.Modulus.Length);
            //byte[] n = parameters.Modulus;
            byte[] e = parameters.Exponent;
            System.Array.Resize<Byte>(ref n, n.Length + 1);
            string base64;
            using (var stream = new MemoryStream())
            {
                stream.Write(ToBytes(sshrsa_bytes.Length), 0, 4);
                stream.Write(sshrsa_bytes, 0, sshrsa_bytes.Length);
                stream.Write(ToBytes(e.Length), 0, 4);
                stream.Write(e, 0, e.Length);
                stream.Write(ToBytes(n.Length), 0, 4);
                stream.Write(n, 0, n.Length);
                stream.Flush();
                base64 = Convert.ToBase64String(stream.ToArray());
            }
            var result = string.Format("ssh-rsa {0}", base64);
            outputStream.Write(result);
        }

What the key generated looks like

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAgD171Y9VeinRALRfU8adS2K0vYHGfKkQwqs8SOQbhURFNtazupsocmpW96dYF346UVVCiKQCYrCW6t0QpGE3ch7onqTvXBszA9mfcuLX9hlhesJqFyUTHxDUopCc2tc5fWYuZ4MeySKuOetBEmPfN3Eu+SWC8j3VS9YzIDjwhkBPcJoxOnv3l7pSxEzGBGQXwdGmL8TFxxsBhue1ajralYPXgJo1nra70ChHcr8PfJvIXigBYCkwnb0KuofbPyhHETo4fNJqCPa1rLjnKoz5iTpyak2SWnhD5FX0/t4juaL/OKNE4YSaAqpWwA9VS1i+y7doeSRc22tm5LHgSLmlxg6h5lPKm5emB840eMLOPvZLS/4uODzFPMo4NFC2ZwNwdlXhcQE9EVtz9EZox1isKpJgShqJPh0sHVH9RnCuBSxW5N79KtsvcXI2zAiLBczKukqU2rTkvYdV1Wkx4zHSvLe42PQuJvSwhwW1tlgyFemd2aRwGDltQyGTPNOZ28E6SGgvxYtB4nvcu8gLyxob4Hz3ysohDB0Z9ZEismSK/8eSeMrBPosTBO77tsjUk1L8v2lHXQ+p1raLpd3ETeae7vZjt6zMFCIhNKDvdJL9b0mIKLB26PMhWG4DzSTJGeIANjiNryWK7y0gdgdPs5953H1EJVRQ0wd2ceFFg2+kpqlrQA=

Using the command ssh-keygen -l -f custom_rsa.pub to test the validity of the key.

$ ssh-keygen -l -f custom_rsa.pub
4104 SHA256:uGO4sHOXXuX1waf+8jrdsWr3/57npF5AuUKUgYVWbCI no comment (RSA)

Solution

  • You resize n both to add a 0 on the left (by manually copying into it starting at index 1) and to add a 0 on the right (via Array.Resize). The latter one is probably getting you into trouble.

    Also, (unrelated) you probably shouldn't use Encoding.Default, but rather whatever encoding you intend. Encoding.ASCII, probably.