Добрый день всем, прежде всего ВНИМАНИЕ! Я провел много исследований и опубликую код, который, я уверен, кому-то поможет. Я выделил курсивом те части, которые были просто пустыми, а «важные» части оставил обычным текстом.
Короткий вопрос: являются ли байты узла SignedInfo (от [60] до [62]) теми, которые действительно подписываются (это означает "sha1ed", затем RSA-ed, затем B64es и инкрустированные в узел SignatureValue ?"
Длинный вопрос: Проблема заключается в том, чтобы просто выполнить стандартный XMLDSIG для XML-файла, созданного мной (это означает, что он всегда будет выглядеть одинаково). Программное обеспечение должно работать на устройствах Android и Windows Phone 6.1 (в частности, на портативном компьютере CN50 intermec). Последняя часть актуальна, потому что это означает, что я не могу использовать упрощенный способ подписания XML, который предоставляет платформа .NET (я смотрю на вас, библиотека System.Security.Cryptography.Xml). Итак, не имея возможности использовать упомянутую библиотеку, я попытался подписать документ «от руки». Наиболее очевидным доказательством и информацией, ориентированной на новичков, которую я смог найти, является эта страница: http://www.di-mgt.com.au/xmldsig2.html, где они делают именно это: полное пошаговое руководство о том, как подписать XML-документ с помощью конвертированной подписи. Часть канонизации меня не беспокоит, поскольку, как я уже сказал, документ будет создан be, и поэтому я приму меры предосторожности, чтобы не вводить элементы, которые потенциально могут испортить часть расчета хеширования. Тем не менее, я пытался выполнить канонизацию в Java с помощью библиотеки XOM, однако результаты были получены там, где… странно.
Прежде чем я продолжу, заполненный данными неподписанный документ был правильно подписан с помощью библиотеки XMLSEC (доступна здесь http://www.aleksey.com/xmlsec/) с помощью следующей команды:
xmlsec --sign --privkey-pem PEMFILE.pem,PEMFILE.pem --node-xpath "(//*[local-name()='Signature' and namespace-uri()='http://www.w3.org/2000/09/xmldsig#'])[last()]" --id-attr:Id "http://www.w3.org/2000/09/xmldsig#:Signature" --id-attr:Id "http://www.w3.org/2000/09/xmldsig#:SignatureValue" UnsignedDocument.xml > SignedDocument.xml
Кроме того, я выполнил подписание с помощью .NET framework на своем компьютере, используя стандартную .NET 4.0 framework со следующим (Примечание 1: это не настоящий производственный код, но в качестве примера это может кому-то помочь. Note2: Здесь я использовал сертификат PFX, установленный на моем компьютере)
X509Store Certificados = new X509Store(StoreName.My, StoreLocation.CurrentUser);
Certificados.Open(OpenFlags.ReadOnly);
foreach (X509Certificate2 Resultado in Certificados.Certificates)
if (Resultado.Thumbprint == "16182C4CB0440D86DBD567B6A9C1963C02E41B9A")
return Resultado;
throw new Exception("No hay un certificado instalado para el RFC que se indicó.");
Подписание выполняется следующим образом
public static void SignXmlFile2(string FileName, string SignedFileName, X509Certificate2 Key)
{
// Create a new XML document.
XmlDocument doc = new XmlDocument();
// Format the document to ignore white spaces.
doc.PreserveWhitespace = true;
// Load the passed XML file using it's name.
doc.Load(new XmlTextReader(FileName));
XmlNode root = doc.DocumentElement;
// Create a SignedXml object.
SignedXml signedXml = new SignedXml(doc);
// Obtenemos el objeto de llave privada del certificado
RSACryptoServiceProvider Llave = Key.PrivateKey as RSACryptoServiceProvider;
Llave.ExportParameters(false);
// Add the key to the SignedXml document.
signedXml.SigningKey = Llave;
// Specify a canonicalization method.
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigC14NWithCommentsTransformUrl;
// Set the InclusiveNamespacesPrefixList property.
XmlDsigC14NWithCommentsTransform canMethod = (XmlDsigC14NWithCommentsTransform)signedXml.SignedInfo.CanonicalizationMethodObject;
// Create a reference to be signed.
Reference reference = new Reference();
reference.Uri = "";
// Add an enveloped transformation to the reference.
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
// Add the reference to the SignedXml object.
signedXml.AddReference(reference);
keyInfo.AddClause(new RSAKeyValue((RSA)Llave));
signedXml.KeyInfo = keyInfo;*/
/* Creamos el nodo <KeyInfo> con el subnodo <X509Data>, poniendo dentro de éste el
certificado, su número de serie y la entidad emisora del mismo (primero estos dos últimos
como subnodo <X509IssuerSerial>), y agregando todo al objeto firmante. */
KeyInfoX509Data NodoX509Data = new KeyInfoX509Data();
NodoX509Data.AddCertificate(Key);
signedXml.KeyInfo = new KeyInfo();
signedXml.KeyInfo.AddClause(NodoX509Data);
// Compute the signature.
signedXml.GetHashCode();
signedXml.ComputeSignature();
// Get the XML representation of the signature and save
// it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Append the element to the XML document.
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
// Save the signed XML document to a file specified
// using the passed string.
XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false));
doc.WriteTo(xmltw);
xmltw.Close();
}
С помощью вышеизложенного я могу получить два эквивалентных документа, и оба правильно подписаны. Итак, у меня есть неподписанный и правильно подписанный документ (полученный из двух источников — C# и XMLSEC), оттуда я знаю правильное значение SHA1 Hash документа (называемое DigestValue) и правильную подпись (называемое SignatureValue). Мне есть с чем сравнивать. Как я уже сказал, я пытался выполнить канонизацию на Java, но смог правильно получить хэш, поэтому вместо того, чтобы биться головой о голову в надежде найти какое-то озарение относительно того, как я все испортил, я просто решил предположим, что входной документ будет канонизирован. И если кто-то скажет: «Это невозможно, потому что разрывы строк изменятся при канонизации», я просто отвечу: в моем входном файле не будет разрывов строк. Еще раз, документ будет создан мной. Следуя этому подходу, я могу получить правильное значение дайджеста неподписанного документа с помощью следующего кода:
ЯВА:
/**
* Generates SHA-1 digest of the provided data.
*
* @param data the data to digest
* @return SHA-1 digest of the provided data.
*/
public static byte[] sha1Digest(byte[] data) {
MessageDigest mdSha1 = null;
try {
mdSha1 = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e1) {
Log.e(LOG_TAG, "Error initializing SHA1 message digest");
/*} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();*/
}
mdSha1.update(data);
byte[] sha1hash = mdSha1.digest();
return sha1hash;
}
Это означает, что входной документ канонически эквивалентен документу, подписанному указанными выше методами.
Байты Sha1
[55, -59, -1, 71, -62, 26, 57, 126, 76, 7, 120, 53, -38, -51, 8, 38, 127, -29, 5, 25]
И в B64
N8X/R8IaOX5MB3g12s0IJn/jBRk=
НАЧАЛО ПРОБЛЕМНОЙ ЧАСТИ
Согласно теории (из разных источников) мне нужно вставить дайджест-значение внутрь узла. Мой подход состоял в том, чтобы прочитать байты пустого, канонизированного узла, подобного этому
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod><DigestValue></DigestValue></Reference></SignedInfo><SignatureValue></SignatureValue><KeyInfo><X509Data><X509Certificate></X509Certificate></X509Data></KeyInfo></Signature>
Вышеперечисленное переводится в байты:
[60, 83, 105, 103, 110, 97, 116, 117, 114, 101, 32, 120, 109, 108, 110, 115, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 48, 57, 47, 120, 109, 108, 100, 115, 105, 103, 35, 34, 62, 60, 83, 105, 103, 110, 101, 100, 73, 110, 102, 111, 62, 60, 67, 97, 110, 111, 110, 105, 99, 97, 108, 105, 122, 97, 116, 105, 111, 110, 77, 101, 116, 104, 111, 100, 32, 65, 108, 103, 111, 114, 105, 116, 104, 109, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 84, 82, 47, 50, 48, 48, 49, 47, 82, 69, 67, 45, 120, 109, 108, 45, 99, 49, 52, 110, 45, 50, 48, 48, 49, 48, 51, 49, 53, 35, 87, 105, 116, 104, 67, 111, 109, 109, 101, 110, 116, 115, 34, 62, 60, 47, 67, 97, 110, 111, 110, 105, 99, 97, 108, 105, 122, 97, 116, 105, 111, 110, 77, 101, 116, 104, 111, 100, 62, 60, 83, 105, 103, 110, 97, 116, 117, 114, 101, 77, 101, 116, 104, 111, 100, 32, 65, 108, 103, 111, 114, 105, 116, 104, 109, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 48, 57, 47, 120, 109, 108, 100, 115, 105, 103, 35, 114, 115, 97, 45, 115, 104, 97, 49, 34, 62, 60, 47, 83, 105, 103, 110, 97, 116, 117, 114, 101, 77, 101, 116, 104, 111, 100, 62, 60, 82, 101, 102, 101, 114, 101, 110, 99, 101, 32, 85, 82, 73, 61, 34, 34, 62, 60, 84, 114, 97, 110, 115, 102, 111, 114, 109, 115, 62, 60, 84, 114, 97, 110, 115, 102, 111, 114, 109, 32, 65, 108, 103, 111, 114, 105, 116, 104, 109, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 48, 57, 47, 120, 109, 108, 100, 115, 105, 103, 35, 101, 110, 118, 101, 108, 111, 112, 101, 100, 45, 115, 105, 103, 110, 97, 116, 117, 114, 101, 34, 62, 60, 47, 84, 114, 97, 110, 115, 102, 111, 114, 109, 62, 60, 47, 84, 114, 97, 110, 115, 102, 111, 114, 109, 115, 62, 60, 68, 105, 103, 101, 115, 116, 77, 101, 116, 104, 111, 100, 32, 65, 108, 103, 111, 114, 105, 116, 104, 109, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 48, 57, 47, 120, 109, 108, 100, 115, 105, 103, 35, 115, 104, 97, 49, 34, 62, 60, 47, 68, 105, 103, 101, 115, 116, 77, 101, 116, 104, 111, 100, 62, 60, 68, 105, 103, 101, 115, 116, 86, 97, 108, 117, 101, 62, 60, 47, 68, 105, 103, 101, 115, 116, 86, 97, 108, 117, 101, 62, 60, 47, 82, 101, 102, 101, 114, 101, 110, 99, 101, 62, 60, 47, 83, 105, 103, 110, 101, 100, 73, 110, 102, 111, 62, 60, 83, 105, 103, 110, 97, 116, 117, 114, 101, 86, 97, 108, 117, 101, 62, 60, 47, 83, 105, 103, 110, 97, 116, 117, 114, 101, 86, 97, 108, 117, 101, 62, 60, 75, 101, 121, 73, 110, 102, 111, 62, 60, 88, 53, 48, 57, 68, 97, 116, 97, 62, 60, 88, 53, 48, 57, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 62, 60, 47, 88, 53, 48, 57, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 62, 60, 47, 88, 53, 48, 57, 68, 97, 116, 97, 62, 60, 47, 75, 101, 121, 73, 110, 102, 111, 62, 60, 47, 83, 105, 103, 110, 97, 116, 117, 114, 101, 62]
Из этого массива я должен получить байты, соответствующие узлу SignedInfo. Это следующие байты (я выделил жирным шрифтом средние байты узла SignedInfo):
[60, 83, 105, 103, 110, 101, 100, 73, 110, 102, 111, 62, 60, 67, 97, 110, 111, 110, 105, 99, 97, 108, 105, 122, 97 , 116, 105, 111, 110, 77, 101, 116, 104, 111, 100, 32, 65, 108, 103, 111, 114, 105, 116, 104, 109, 61, 34, 104, 116, 116 , 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 84, 82, 47, 50, 48, 48, 49, 47, 82, 69 , 67, 45, 120, 109, 108, 45, 99, 49, 52, 110, 45, 50, 48, 48, 49, 48, 51, 49, 53, 35, 87, 105, 116, 104, 67 , 111, 109, 109, 101, 110, 116, 115, 34, 62, 60, 47, 67, 97, 110, 111, 110, 105, 99, 97, 108, 105, 122, 97, 116, 105 , 111, 110, 77, 101, 116, 104, 111, 100, 62, 60, 83, 105, 103, 110, 97, 116, 117, 114, 101, 77, 101, 116, 104, 111, 100 , 32, 65, 108, 103, 111, 114, 105, 116, 104, 109, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51 , 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 48, 57, 47, 120, 109, 108, 100, 115, 105, 103, 35, 114, 115, 97, 45 , 115, 104, 97, 49, 34, 62, 60, 47, 83, 105, 103, 110, 97, 116 , 117, 114, 101, 77, 101, 116, 104, 111, 100, 62, 60, 82, 101, 102, 101, 114, 101, 110, 99, 101, 32, 85, 82, 73, 61 , 34, 34, 62, 60, 84, 114, 97, 110, 115, 102, 111, 114, 109, 115, 62, 60, 84, 114, 97, 110, 115, 102, 111, 114, 109 , 32, 65, 108, 103, 111, 114, 105, 116, 104, 109, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51 , 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 48, 57, 47, 120, 109, 108, 100, 115, 105, 103, 35, 101, 110, 118, 101 , 108, 111, 112, 101, 100, 45, 115, 105, 103, 110, 97, 116, 117, 114, 101, 34, 62, 60, 47, 84, 114, 97, 110, 115, 102 , 111, 114, 109, 62, 60, 47, 84, 114, 97, 110, 115, 102, 111, 114, 109, 115, 62, 60, 68, 105, 103, 101, 115, 116, 77 , 101, 116, 104, 111, 100, 32, 65, 108, 103, 111, 114, 105, 116, 104, 109, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119 , 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 48, 57, 47, 120, 109, 108, 100, 115, 105, 103 , 35, 115, 104, 97, 49, 34, 62, 60, 47, 68, 105, 103, 101, 115, 116, 77, 101, 116, 104, 111, 100, 62, 60, 68, 105, 103, 101, 115, 116, 86, 97, 108, 117, 101, 62 , 60, 47, 68, 105, 103, 101, 115, 116, 86, 97, 108, 117, 101, 62, 60, 47, 82, 101, 102, 101, 114, 101, 110 , 99, 101, 62, 60, 47, 83, 105, 103, 110, 101, 100, 73, 110, 102, 111, 62]
В этот массив байтов я должен вставить байты, соответствующие Sha1 документа, закодированного в B64.
Байты Sha1
[55, -59, -1, 71, -62, 26, 57, 126, 76, 7, 120, 53, -38, -51, 8, 38, 127, -29, 5, 25]
И в B64
N8X/R8IaOX5MB3g12s0IJn/jBRk=
И это обратно в байты:
[78, 56, 88, 47, 82, 56, 73, 97, 79, 88, 53, 77, 66, 51, 103, 49, 50, 115, 48, 73, 74, 110, 47, 106, 66, 82, 107, 61]
Тогда массив SignedInfo с присоединенным хэшем выглядит следующим образом:
[60, 83, 105, 103, 110, 101, 100, 73, 110, 102, 111, 62, 60, 67, 97, 110, 111, 110, 105, 99, 97, 108, 105, 122, 97 , 116, 105, 111, 110, 77, 101, 116, 104, 111, 100, 32, 65, 108, 103, 111, 114, 105, 116, 104, 109, 61, 34, 104, 116, 116 , 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 84, 82, 47, 50, 48, 48, 49, 47, 82, 69 , 67, 45, 120, 109, 108, 45, 99, 49, 52, 110, 45, 50, 48, 48, 49, 48, 51, 49, 53, 35, 87, 105, 116, 104, 67 , 111, 109, 109, 101, 110, 116, 115, 34, 62, 60, 47, 67, 97, 110, 111, 110, 105, 99, 97, 108, 105, 122, 97, 116, 105 , 111, 110, 77, 101, 116, 104, 111, 100, 62, 60, 83, 105, 103, 110, 97, 116, 117, 114, 101, 77, 101, 116, 104, 111, 100 , 32, 65, 108, 103, 111, 114, 105, 116, 104, 109, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51 , 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 48, 57, 47, 120, 109, 108, 100, 115, 105, 103, 35, 114, 115, 97, 45 , 115, 104, 97, 49, 34, 62, 60, 47, 83, 105, 103, 110, 97, 116 , 117, 114, 101, 77, 101, 116, 104, 111, 100, 62, 60, 82, 101, 102, 101, 114, 101, 110, 99, 101, 32, 85, 82, 73, 61 , 34, 34, 62, 60, 84, 114, 97, 110, 115, 102, 111, 114, 109, 115, 62, 60, 84, 114, 97, 110, 115, 102, 111, 114, 109 , 32, 65, 108, 103, 111, 114, 105, 116, 104, 109, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51 , 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 48, 57, 47, 120, 109, 108, 100, 115, 105, 103, 35, 101, 110, 118, 101 , 108, 111, 112, 101, 100, 45, 115, 105, 103, 110, 97, 116, 117, 114, 101, 34, 62, 60, 47, 84, 114, 97, 110, 115, 102 , 111, 114, 109, 62, 60, 47, 84, 114, 97, 110, 115, 102, 111, 114, 109, 115, 62, 60, 68, 105, 103, 101, 115, 116, 77 , 101, 116, 104, 111, 100, 32, 65, 108, 103, 111, 114, 105, 116, 104, 109, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119 , 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 48, 47, 48, 57, 47, 120, 109, 108, 100, 115, 105, 103 , 35, 115, 104, 97, 49, 34, 62, 60, 47, 68, 105, 103, 101, 115, 116, 77, 101, 116, 104, 111, 100, 62, 60, 68, 105, 103, 101, 115, 116, 86, 97, 108, 117, 101, 62 , 78, 56, 88, 47, 82, 56, 73, 97, 79, 88, 53, 77, 66, 51, 103, 49, 50, 115, 48, 73, 74, 110, 47, 106, 66 , 82, 107, 61, 60, 47, 68, 105, 103, 101, 115, 116, 86, 97, 108, 117, 101, 62, 60, 47, 82, 101, 102, 101 , 114, 101, 110, 99, 101, 62, 60, 47, 83, 105, 103, 110, 101, 100, 73, 110, 102, 111, 62]
Приведенный выше массив, преобразованный в строку:
<SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod><DigestValue>N8X/R8IaOX5MB3g12s0IJn/jBRk=</DigestValue></Reference></SignedInfo>
Теперь это байты, которые (я думаю) должны быть зашифрованы RSA. Я применил несколько методов подписи:
- Java с использованием класса Cipher (Privatekey читается через файл PEM)
- Java с использованием класса Signature (Privatekey читается через файл PEM)
- C # с использованием библиотек BouncyCastle (в эмуляторе Windows Mobile) (ключ читается через CertificateStore и преобразуется в формат BC)
- С# с использованием RSAFormatter (ключ, полученный через хранилище сертификатов Windows)
И в каждом из них я получил один и тот же результат подписи для введенных байтов:
[2, -125, 23, -84, -28, -120, -45, -72, -73, -105, -71, -25, -100, -81, -77, 119, 98, 0, 28, -124, -92, 116, -108, -9, 22, -90, -103, -119, 52, 105, 53, 24, -59, -87, 25, -38, -31, -15, 39, 104, -4, 0, 62, -117, 103, -79, 112, 65, -43, -49, -26, -126, -108, 120, -4, -44, 73, -33, 87, 39, 84, 7, 107, -81, 91, 61, -86, 100, 103, -112, -123, -118, 98, 85, -14, -88, -92, -45, -79, 3, -28, -18, 64, 2, -125, 53, -70, 100, -10, 86, -52, 17, -22, 110, -126, -100, -115, 45, -18, 99, -79, -92, -8, -120, -104, -63, 43, 70, -41, 98, 121, -68, -8, 60, -93, -95, -83, 83, -86, 75, -128, 120, -6, -11, 24, -124, 70, -128]
Aomxrosi07i3l7nnnk + zd2iahiskdjt3fqazitrpnrjfqrna4fenapwapotn sxbb1c / mgpr4 / nrj31cnvadrrrr1s9qmrnkiwkylxyqkttsqpk7kacgzw6zpzq zbhqbokcjs3uy7gk + iiywstg12j5vpg8o6gtu6plghj69rieroa =
Поскольку я получаю тот же результат для одних и тех же входных данных, ошибка заключается не в процедуре подписания, а в данных, которые я ввожу. И тут я не могу найти решение. Кстати, подпись действительна, если я проверяю ее как строку с соответствующим открытым ключом или сертификатом... ошибка возникает, когда я присоединяю узел подписи к исходному документу и проверяю его как XMLDSIG. Подпись принимает в основном три входа. Байты для подписи. Алгоритм закрытого ключа. Ключ и алгоритм в порядке (я думаю), тогда проблема должна быть в подписываемых байтах, однако я не могу найти, что я делаю неправильно. Если кто-то может помочь мне, я буду очень благодарен.
Я включаю некоторый код ниже, чтобы показать методы, которые я использую для получения одной и той же подписи на разных языках и устройствах.
Это общедоступный статический байт JAVA. Строка stringAFirmar = новая строка (bSignedInfo, "ISO-8859-1");
//ONE WAY OF SIGNING
byte[] signedInfoSha1Digest = sha1Digest(bSignedInfo);
//byte[] bytesCS = new byte[]{55,-59,-1,71,-62,26,57,126,76,7,120,53,-38,-51,8,38,127,-29,5,25};
String vSignedInfoSha1DigestString64 = Base64.encodeToString(signedInfoSha1Digest, Base64.DEFAULT);
byte[] signedInfoDerSha1Digest = mergeArrays(DER_SHA1_DIGEST_IDENTIFIER, signedInfoSha1Digest);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding","BC");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] signatureBytes = cipher.doFinal(signedInfoDerSha1Digest);
String base64RsaSignature1 = base64encode(signatureBytes, true);
//String vFirma = bytesToHex(signatureBytes);
//ANOTHER WAY OF SIGNING
Signature instance2 = Signature.getInstance("SHA1withRSA");
instance2.initSign(privateKey);
instance2.update(bSignedInfo);
byte[] bFirma3 = instance2.sign();
String base64RsaSignature2 = base64encode(bFirma3, true);
Log.i("Log","nada");
//VALIDATE THE RESULT
Signature instanceValida = Signature.getInstance("SHA1withRSA");
instanceValida.initVerify(Certificado);
instanceValida.update(bSignedInfo);
if(instanceValida.verify(bFirma3)==true)
Log.i("Validacion","La firma es valida");
else
Log.i("Validacion","La firma NO ES valida");
return bFirma3;
}
catch (Throwable e) {
Log.e(LOG_TAG, "Error generating signature for XML", e);
throw e;
}
}
Это С#
public static void SignXmlFile3(string Cadena, X509Certificate2 Key)
{
/*opcion 1
RSACryptoServiceProvider RSA = Key.PrivateKey as RSACryptoServiceProvider;
RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter(RSA);
* */
//Opcion 2
RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter();
RSAFormatter.SetKey(Key.PrivateKey as RSACryptoServiceProvider);
RSAFormatter.SetHashAlgorithm("SHA1");
SHA1Managed SHhash = new SHA1Managed();
var bytes3 = Encoding.UTF8.GetBytes(Cadena);
var bytes = Convert.FromBase64String(Cadena);
byte[] SignedHashValue = RSAFormatter.CreateSignature(SHhash.ComputeHash(bytes));
string signature = System.Convert.ToBase64String(SignedHashValue);
}
Это С# с использованием bouncyCastle на WindowsPhone
public String Sign(String data, String privateModulusHexString, String privateExponentHexString, X509Certificate2 vX509Certificate2)
{
//var test = DotNetUtilities.FromX509Certificate(vX509Certificate2);
/* Make the key */
RsaKeyParameters key = MakeKey(privateModulusHexString, privateExponentHexString, true);
/* Init alg */
ISigner sig = SignerUtilities.GetSigner("SHA1withRSA");
/* Populate key */
sig.Init(true, key);
/* Get the bytes to be signed from the string */
var bytes = Encoding.UTF8.GetBytes(data);
/* Calc the signature */
sig.BlockUpdate(bytes, 0, bytes.Length);
byte[] signature = sig.GenerateSignature();
/* Base 64 encode the sig so its 8-bit clean */
var signedString = Convert.ToBase64String(signature);
return signedString;
}