문제

I'm porting some Java code to C#, but it appears as though the public key padding between Java and C# is inconsistent.

Here is my Java code:

package Encryption;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.io.ByteArrayInputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import javax.xml.bind.DatatypeConverter;
/**
 *
 * @author Cameron
 */
public class Encryptiontest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here

        String publicKey = "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";
        ByteArrayInputStream bytearrayinputstream = new ByteArrayInputStream(DatatypeConverter.parseBase64Binary(publicKey));
        X509Certificate x509certificate;
        try
        {
            x509certificate = (X509Certificate)CertificateFactory.getInstance("X.509").generateCertificate(bytearrayinputstream);
            RSAPublicKey key = (RSAPublicKey)x509certificate.getPublicKey();
            System.out.println(DatatypeConverter.printBase64Binary(key.getEncoded()));
        }
        catch (CertificateException certificateexception)
        {
        }
    }

}

When I print the base64 representation of the RSAPublicKey, this is what I get:

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvUihVNnWYpu3uJmcLy+PBecKu4ziVD7OIeZ/V+tJkXbc5+6OW8G+QDtJKuJkkuxGNLBNmLHbCyXsJ/US3kKkU7/7yK7jfWRNdqAKJdDTVxsWnxlo+/28ScGrAV6wK2bbK8GQBpsYRn1HKGCGceWIBCSqUfI7rwgwDnvqcW5PeivORd4+or5DdhgUMwiV5Vr2fvdcAiQR1CKgMphxO4+OmZ4khpB/HT/xS4FscvfFsSBLM37jBMrnhY5yNKPeHZB2eYvehnnw22NFHJNksa+vVFXL9aJcZWJc/bqqlhlhL8eLdYSR/KA006PSInW8yWtd4IFVKJ1Moa41gCUZL81voQIDAQAB

However, the result is different with C# with the same base64 public key. Here is my C# code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace EncryptionTest
{
    class Program
    {
        static void Main(string[] args)
        {
            String publicKey = "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";
            byte[] data = Convert.FromBase64String(publicKey);

            X509Certificate x509certificate = new X509Certificate(data);
            byte[] rsaPublicKey = x509certificate.GetPublicKey();

            string base64 = Convert.ToBase64String(rsaPublicKey);

            Console.WriteLine(base64);
            Console.ReadKey();
        }
    }
}

C# output:

MIIBCgKCAQEAvUihVNnWYpu3uJmcLy+PBecKu4ziVD7OIeZ/V+tJkXbc5+6OW8G+QDtJKuJkkuxGNLBNmLHbCyXsJ/US3kKkU7/7yK7jfWRNdqAKJdDTVxsWnxlo+/28ScGrAV6wK2bbK8GQBpsYRn1HKGCGceWIBCSqUfI7rwgwDnvqcW5PeivORd4+or5DdhgUMwiV5Vr2fvdcAiQR1CKgMphxO4+OmZ4khpB/HT/xS4FscvfFsSBLM37jBMrnhY5yNKPeHZB2eYvehnnw22NFHJNksa+vVFXL9aJcZWJc/bqqlhlhL8eLdYSR/KA006PSInW8yWtd4IFVKJ1Moa41gCUZL81voQIDAQAB

Why are the two similar, but padded differently? How do I make the C# output look like the Java output?

도움이 되었습니까?

해결책

The Java output is the DER encoding of the ASN.1 SubjectPublicKeyInfo, as specified in RFC 5280, section 4.1. The C# output is the DER encoding of the ASN.1 RSAPublicKey, as specific in many places include RFC 2313, section 7..

Here is an easy to use online ASN.1 decoder that I find convenient. You can paste the base64 directly into the form and get it decoded.

I'm not really a .NET expert, but hunting around I think you might get something closer, if not identical, by instead using the X509Certificate2 class. You can construct an X509Certificate2 object from an X509Certificate object. The X509Certificate2 class contains a PublicKey property that you can access. That object appears to have an EncodedKeyValue, and following this seemingly endless chain gets you the raw data. In other words, something like:

X509Certificate2 x509certificate2 = new X509Certificate2(data);
byte[] rsaPublicKey = x509certificate2.PublicKey.EncodedKeyValue.RawData;

should work. But I haven't tested it.

다른 팁

Here is another way you could get the Base64 representation of the public key:

string base64 = Convert.ToBase64String(x509certificate.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks);

For details please see Exporting a Certificate as BASE-64 encoded .cer

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top