Имеется модуль подписания XML документа в формате XMLDsig. Модуль написан c помощью языка Java в связки с КриптоПро JCP. При подписании используется ключевая пара хранящаяся в JaCarta PKI (OCF Store).
Суть алгоритма состоит в следующем:
1) Преобразуем входной XML , удаляя из него все переносы строк и табуляции, т.к в дальнейшем при отправки содержимое передаётся в качестве параметра Post Запроса.
String fileCont = new String(Files.readAllBytes(inFile.toPath()));
fileCont=fileCont.replaceAll("\n", "").replaceAll("\r", "").replaceAll("\t", "");
fileContent = fileCont.getBytes();
2) Вычисляю подпись от полученной строки
if (!ru.CryptoPro.JCPxml.XmlInit.isInitialized()) {
ru.CryptoPro.JCPxml.XmlInit.init();
}
// инициализация объекта чтения XML-документа
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
final DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
final Document doc = documentBuilder.parse(new ByteArrayInputStream(fileContent));
ElementProxy.setDefaultPrefix(Constants.SignatureSpecNS, "");
XMLSignature sig = new XMLSignature(doc, "", signMethod, canonicalizationMethod);
Element anElement = doc.getDocumentElement();
anElement.appendChild(sig.getElement());
Transforms transforms = new Transforms(doc);
transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
sig.addDocument("", transforms, digestMethod);
KeyStore keyStore = KeyStore.getInstance("OCFStore","JCP");
keyStore.load(null, null);
if(keyStore==null){
System.out.println("KeyStore is null");
}
PrivateKey privateKey = (PrivateKey) keyStore.getKey("alias", new char[]{});
X509Certificate x509Cert = (X509Certificate) keyStore.getCertificate("alias");
sig.addKeyInfo(x509Cert);
sig.sign(privateKey);
3) Подпись встраиваю без использования DOM, т.к при его использовании менялся порядок атрибутов и было подозрение, что в этом и была ошибка. Перевожу <Signature> в строку и встраиваю её перед первым знаком ‘<’ справа.
Element d = sig.getElement();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
StreamResult strRes = new StreamResult(new StringWriter());
trans.transform(new DOMSource(d), strRes);
String strSignBlock = strRes.getWriter().toString().replaceAll("\n", "").replaceAll("\r", "").replaceAll("\t", "").replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>","");
int n=0;
int lenth = fileCont.toCharArray().length-1;
for (int i = lenth ; i>0;i--){
n++;
if (fileCont.charAt(i)=='<'){
break;
}
}
String beforeFinal = fileCont.substring(0,lenth-n+1);
String finalBlock = fileCont.substring(lenth-n+1);
String signDoc = beforeFinal+strSignBlock+finalBlock;
FileWriter fw = new FileWriter(f);
fw.append(signDoc);
fw.close();
На приёмной стороне проверяется средствами КриптоПро DSS (сделал вывод исходя их скриншотов). Ошибку которую получаем: 'msg' => 'Ошибка при проверке ЭЦП -> invalid -> invalidSignatureValue -> проверка подписи средствами xmlsec завершилась с ошибкой',
Помогите разобраться в чем может быть дело.