OpenSSL wrapper returns the OpenSSL.X509.X509Certificate.PublicKey.GetRSA().PublicKeyAsPEM public key in the form:

 -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjSqa7RcgUt0rfK1YHGJj2fqgs 1jWjfzS5rvm99b33z3AVxMo8xbqKSNt2t8oYVVLTGQo/75cN5ZCZPWT9ebz9oU0L HtyIyd4HjPEwvw143b7224Aq4giimOxXZkfT0T5Ey3l6YH4jGAOgc5x6/DyHzbhH BtKeoadwUSEM0MyeUQIDAQAB -----END PUBLIC KEY----- 

I need to convert it to .NET System.Security.Cryptography.X509Certificates.GetPublicKey() , which gives the value of the public key:

 0x30 0x81 0x89 0x02 0x81 0x81 0x00 0xa3 0x4a 0xa6 0xbb 0x45 0xc8 0x14 0xb7 0x4a 0xdf 0x2b 0x56 0x07 0x18 0x98 0xf6 0x7e 0xa8 0x2c 0xd6 0x35 0xa3 0x7f 0x34 0xb9 0xae 0xf9 0xbd 0xf5 0xbd 0xf7 0xcf 0x70 0x15 0xc4 0xca 0x3c 0xc5 0xba 0x8a 0x48 0xdb 0x76 0xb7 0xca 0x18 0x55 0x52 0xd3 0x19 0x0a 0x3f 0xef 0x97 0x0d 0xe5 0x90 0x99 0x3d 0x64 0xfd 0x79 0xbc 0xfd 0xa1 0x4d 0x0b 0x1e 0xdc 0x88 0xc9 0xde 0x07 0x8c 0xf1 0x30 0xbf 0x0d 0x78 0xdd 0xbe 0xf6 0xdb 0x80 0x2a 0xe2 0x08 0xa2 0x98 0xec 0x57 0x66 0x47 0xd3 0xd1 0x3e 0x44 0xcb 0x79 0x7a 0x60 0x7e 0x23 0x18 0x03 0xa0 0x73 0x9c 0x7a 0xfc 0x3c 0x87 0xcd 0xb8 0x47 0x06 0xd2 0x9e 0xa1 0xa7 0x70 0x51 0x21 0x0c 0xd0 0xcc 0x9e 0x51 0x02 0x03 0x01 0x00 0x01 

How can I convert (without using the file system, i.e. constructors or methods that load the certificate from a file)?

ps tried stupidly Convert.FromBase64String(PublicKeyAsPEM с вырезанными тегами BEGIN и END) , but the result is all the same.


Second example:

 -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkxIbLYQrXNOYR8CE04Lm /M5mGO7EIwPwxJdkC94GGHlJfElTwzPrvM9c/NQuGO1sutmvNTqt6D+xeSaILU1L dPgTUm2hRwbx6DYUZdtjweC+91gy6LnmwhySfyGv5HRXmIhsisNy89dXbEBk/cTU evjnaXMbBv89uFJPwgVN2wg3lNilt4fq//Z+WNqGV1n4zRYNHplIOG17ceZjkXXr eJpYSxQtJUkZy/p8oEEfT/5zOkZ/GeXfpiuW+j9zGnJhTgWjy7izZhFO+jJXkRdk 5eUV/smwUFwUYaRGF/dYQcQIBQ2s7UU4QNPIXUBGROJKE9AjrXNu5FczlmZmbiv1 fQIDAQAB -----END PUBLIC KEY----- 0x30 0x82 0x01 0x0a 0x02 0x82 0x01 0x01 0x00 0x93 0x12 0x1b 0x2d 0x84 0x2b 0x5c 0xd3 0x98 0x47 0xc0 0x84 0xd3 0x82 0xe6 0xfc 0xce 0x66 0x18 0xee 0xc4 0x23 0x03 0xf0 0xc4 0x97 0x64 0x0b 0xde 0x06 0x18 0x79 0x49 0x7c 0x49 0x53 0xc3 0x33 0xeb 0xbc 0xcf 0x5c 0xfc 0xd4 0x2e 0x18 0xed 0x6c 0xba 0xd9 0xaf 0x35 0x3a 0xad 0xe8 0x3f 0xb1 0x79 0x26 0x88 0x2d 0x4d 0x4b 0x74 0xf8 0x13 0x52 0x6d 0xa1 0x47 0x06 0xf1 0xe8 0x36 0x14 0x65 0xdb 0x63 0xc1 0xe0 0xbe 0xf7 0x58 0x32 0xe8 0xb9 0xe6 0xc2 0x1c 0x92 0x7f 0x21 0xaf 0xe4 0x74 0x57 0x98 0x88 0x6c 0x8a 0xc3 0x72 0xf3 0xd7 0x57 0x6c 0x40 0x64 0xfd 0xc4 0xd4 0x7a 0xf8 0xe7 0x69 0x73 0x1b 0x06 0xff 0x3d 0xb8 0x52 0x4f 0xc2 0x05 0x4d 0xdb 0x08 0x37 0x94 0xd8 0xa5 0xb7 0x87 0xea 0xff 0xf6 0x7e 0x58 0xda 0x86 0x57 0x59 0xf8 0xcd 0x16 0x0d 0x1e 0x99 0x48 0x38 0x6d 0x7b 0x71 0xe6 0x63 0x91 0x75 0xeb 0x78 0x9a 0x58 0x4b 0x14 0x2d 0x25 0x49 0x19 0xcb 0xfa 0x7c 0xa0 0x41 0x1f 0x4f 0xfe 0x73 0x3a 0x46 0x7f 0x19 0xe5 0xdf 0xa6 0x2b 0x96 0xfa 0x3f 0x73 0x1a 0x72 0x61 0x4e 0x05 0xa3 0xcb 0xb8 0xb3 0x66 0x11 0x4e 0xfa 0x32 0x57 0x91 0x17 0x64 0xe5 0xe5 0x15 0xfe 0xc9 0xb0 0x50 0x5c 0x14 0x61 0xa4 0x46 0x17 0xf7 0x58 0x41 0xc4 0x08 0x05 0x0d 0xac 0xed 0x45 0x38 0x40 0xd3 0xc8 0x5d 0x40 0x46 0x44 0xe2 0x4a 0x13 0xd0 0x23 0xad 0x73 0x6e 0xe4 0x57 0x33 0x96 0x66 0x66 0x6e 0x2b 0xf5 0x7d 0x02 0x03 0x01 0x00 0x01 

    2 answers 2

    Basically, Convert.FromBase64String helps. Just before the data you need go 22 bytes I do not know what. And I'm not sure that these bytes are always 22.
    Here is the code:

     string s = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjSqa7RcgUt0rfK1YHGJj2fqgs1jWjfzS5rvm99b33z3AVxMo8xbqKSNt2t8oYVVLTGQo/75cN5ZCZPWT9ebz9oU0LHtyIyd4HjPEwvw143b7224Aq4giimOxXZkfT0T5Ey3l6YH4jGAOgc5x6/DyHzbhHBtKeoadwUSEM0MyeUQIDAQAB"; byte[] bytes = Convert.FromBase64String(s).Skip(22).ToArray(); DyHzbhHBtKeoadwUSEM0MyeUQIDAQAB"; string s = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjSqa7RcgUt0rfK1YHGJj2fqgs1jWjfzS5rvm99b33z3AVxMo8xbqKSNt2t8oYVVLTGQo/75cN5ZCZPWT9ebz9oU0LHtyIyd4HjPEwvw143b7224Aq4giimOxXZkfT0T5Ey3l6YH4jGAOgc5x6/DyHzbhHBtKeoadwUSEM0MyeUQIDAQAB"; byte[] bytes = Convert.FromBase64String(s).Skip(22).ToArray(); 

    The contents of the bytes array is the same as the one you specified.


    If you have another example (preferably with a key of a different length), I may be able to understand how many bytes to cut off.
    By the way, the last byte of these 22 is zero. Maybe this is a sign of the end of the title.


    There is a site where the key data structure is decrypted by element. It is not completely understood to me yet, but the following code was born:

     private static byte[] DecodePublicKey(string key) { byte[] bytes = Convert.FromBase64String(key); int index = 1; while (index < bytes.Length) { byte current = bytes[index]; switch (current) { case 0: index += 1; byte[] outkey = new byte[bytes.Length - index]; Array.Copy(bytes, index, outkey, 0, outkey.Length); return outkey; case 0x03: case 0x30: index += 1; break; case 0x81: index += 2; break; case 0x82: index += 3; break; default: index += current + 1; break; } } return null; } 
    • Added a second example. - Alexis
    • one
      @ z668 As expected, in the second example, you need to cut off a different number of bytes, namely, 24. Dependence has not yet been found. - Dmitry D.
    • one
      @ z668 Added a method to the response that cuts the required number of bytes in both examples. However, it is possible that the switch will have to fill up and other options. - Dmitry D.
    • Thank. Now it is clear that this is ASN1 with DER encoding. Now it will be easier, I went to pick BouncyCastle, for sure there is something there. - Alexis

    Out of the situation in another way:

     var netX509Cert = new System.Security.Cryptography.X509Certificates.X509Certificate(); netX509Cert.Import(certificate.DER); // Импортируем OpenSSL сертификат byte[] publicKey = netX509Cert.GetPublicKey(); // Получаем байты чистого ключа, без прочих ASN.1 значений 

    ps for good of course you just need to connect the ASN.1 parser, parse the children and take the value of the penultimate Integer.