Как сгенерировать подпись на основе файла XML? - PullRequest
0 голосов
/ 09 февраля 2020

, пожалуйста, помогите мне решить следующее: у меня есть код на Java java код ниже:

StringBuilder fullText;
KeyStore p12 = KeyStore.getInstance("PKCS12");
p12.load(new FileInputStream("FileName.p12"), "1234".toCharArray());

Key key = (Key) p12.getKey("1", "1234".toCharArray());

//signing
Signature signer = Signature.getInstance("SHA1withRSA");

signer.initSign((PrivateKey) key);
signer.update(fullText.toString().getBytes());
b`yte[] digitalSignature = signer.sign();

String base64sign = new String(Base64.getEncoder().encode(digitalSignature));

Я пытался воспроизвести его на платформе. Net. Я создаю код на платформе. NET 3.5. Код на X ++ ниже:

public static boolean Encrypt(str sXmlDoc)
{
    boolean bSuccess = false;

    System.Security.Cryptography.X509Certificates.X509Certificate2 p12;
    System.Security.Cryptography.AsymmetricAlgorithm key;

    str sBase64Cert;
    str sBase64Xml;
    str sBase64Sign;

    str sTmp;

    System.Byte[] byteArray;
    System.Security.Cryptography.Xml.Signature signer;
    System.Exception  ex;
    str sKeyPublic;
    System.Byte[] keyPublic;
    System.Int32 myInt32;
    int myInt;
    System.Byte[] byteTmp, byteTmp2;
    System.Text.ASCIIEncoding txtEncoder;
    System.Security.Cryptography.Xml.KeyInfo keyInfo;
    System.Security.Cryptography.Xml.SignedXml signedXml;
    System.Xml.XmlDocument xmlDocument;
    System.Xml.XmlElement xmlElement;
    System.Security.Cryptography.Xml.SignedInfo signedInfo;
    System.Security.Cryptography.Xml.Reference reference;
    System.Security.Cryptography.Xml.XmlDsigEnvelopedSignatureTransform env;

    System.Security.Cryptography.Xml.RSAKeyValue rsaKeyValue;
    System.Security.Cryptography.RSA rsaKey;

    try
    {


        p12 = new System.Security.Cryptography.X509Certificates.X509Certificate2("fileName.p12", "pass");
        if (p12)
        {
            //Signature

            //TEST
            if (p12.get_HasPrivateKey())
            {
                key = p12.get_PrivateKey();
                rsaKey = p12.get_PrivateKey();

                xmlDocument = new System.Xml.XmlDocument();
                xmlDocument.set_PreserveWhitespace(true); //Allow white spaces
                xmlDocument.LoadXml(sXmlDoc);
                signedXml = new System.Security.Cryptography.Xml.SignedXml(xmlDocument);
                signedXml.set_SigningKey(key);
                keyInfo = new System.Security.Cryptography.Xml.KeyInfo();
                rsaKeyValue = new System.Security.Cryptography.Xml.RSAKeyValue(rsaKey);
                keyInfo.AddClause(rsaKeyValue);
                signedXml.set_KeyInfo(keyInfo);
                // Create a reference to be signed.
                //System.Security.Cryptography.Xml.Reference reference;
                reference = new System.Security.Cryptography.Xml.Reference();
                reference.set_Uri("");
                // Add an enveloped transformation to the reference.
                env = new System.Security.Cryptography.Xml.XmlDsigEnvelopedSignatureTransform();
                reference.AddTransform(env);
                // Add the reference to the SignedXml object.
                signedXml.AddReference(reference);
                signedXml.set_KeyInfo(keyInfo);
                signedXml.ComputeSignature();
                xmlElement = signedXml.GetXml();
                signer = new System.Security.Cryptography.Xml.Signature();
                signer = signedXml.get_Signature();
                signedInfo = new System.Security.Cryptography.Xml.SignedInfo();
                signedInfo = signer.get_SignedInfo();
                byteTmp = signer.get_SignatureValue();
                sTmp = System.Convert::ToBase64String(byteTmp);
                sBase64Sign = "<signature>"+sTmp+"</signature>";
                info(sBase64Sign);
            }
        }

    }
    catch (Exception::CLRError)
    {
        ex = ClrInterop::getLastException();
        if (ex != null)
        {
           ex = ex.get_InnerException();
           if (ex != null)
           {
               error(ex.ToString());
           }
        }
    }

    return bSuccess;
}

Но результат отличается от того, что я получил на java. Я открыл ключ p12. Я подписал жало XML и получил подпись для этого XML, но получил неверную строку. Что я сделал не так?

Ответы [ 2 ]

1 голос
/ 10 февраля 2020

Код Java ничего не говорит о XML, поэтому я не знаю, узнали ли вы что-нибудь о переносе кода, но если вы все же будете использовать XML в C#, то произойдет сбой.

Короче говоря, вам нужно напрямую использовать функции RSA. Начиная с RSA.Create() может иметь смысл в большинстве языков. Однако NET скорее основан на сертификате / ключе (вы выполняете операции над ключом, а не , используя ключ, что бы там ни было, а закрытые ключи считаются частью сертификат, что они принадлежат). Поэтому использование конструктора для чтения PKCS # 12 , вероятно, является лучшей отправной точкой.

Вот и все для этого небольшого урока. Я не верю ни на секунду, что вы подумали, что ваш код будет правильным портом, поэтому начните сначала. Удачное программирование.


РЕДАКТИРОВАТЬ: О, последний совет: SHA1withRSA - это RSA, использующий дополнение PKCS # 1 v1.5 для генерации подписи, используя SHA-1 в качестве основной функции ha sh (что, конечно, значит он разбит и тд).

0 голосов
/ 17 февраля 2020

Лучший способ подписать XML на. NET - использовать библиотеку Bouncy Castle. Я надеюсь, что кто-нибудь за один день решит это на. NET framework, без использования внешней библиотеки, но решение нашлось с помощью BounsyCastle . Этот код на C# используется BouncyCastle.

string item = string.Empty;

Pkcs12Store p12 = new Pkcs12Store();
p12.Load(_p12, _p12_psw.ToCharArray());

string alias = "";
foreach (string al in p12.Aliases)
{
    if (p12.IsKeyEntry(al) && p12.GetKey(al).Key.IsPrivate)
    {
        alias = al;
        break;
    }
}

//signature
var data = Encoding.UTF8.GetBytes(xmlDoc);
ISigner signer = SignerUtilities.GetSigner("SHA1withRSA");
signer.Init(true,p12.GetKey(alias).Key);
signer.BlockUpdate(data, 0, data.Length);

var sign = signer.GenerateSignature();

string base64Sign = Convert.ToBase64String(sign);
item = "<signature>"+base64Sign+"</signature>", base64Sign);
...