Path: blob/master/test/jdk/javax/xml/crypto/dsig/PSSSpec.java
41152 views
/*1* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import jdk.test.lib.Asserts;24import jdk.test.lib.Utils;25import jdk.test.lib.security.XMLUtils;26import org.w3c.dom.Document;2728import javax.crypto.spec.SecretKeySpec;29import javax.xml.crypto.MarshalException;30import javax.xml.crypto.dsig.DigestMethod;31import javax.xml.crypto.dsig.SignatureMethod;32import javax.xml.crypto.dsig.XMLSignatureFactory;33import javax.xml.crypto.dsig.dom.DOMValidateContext;34import javax.xml.crypto.dsig.spec.RSAPSSParameterSpec;35import java.security.KeyPairGenerator;36import java.security.spec.MGF1ParameterSpec;37import java.security.spec.PSSParameterSpec;3839/**40* @test41* @bug 824130642* @library /test/lib43* @modules java.xml.crypto44* @summary Testing marshal and unmarshal of RSAPSSParameterSpec45*/46public class PSSSpec {47private static final String P2SM = "//ds:Signature/ds:SignedInfo/ds:SignatureMethod";48private static final String P2PSS = P2SM + "/pss:RSAPSSParams";49private static final String P2MGF = P2PSS + "/pss:MaskGenerationFunction";5051private static final PSSParameterSpec DEFAULT_SPEC52= new PSSParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), 32, PSSParameterSpec.TRAILER_FIELD_BC);5354public static void main(String[] args) throws Exception {55unmarshal();56marshal();57spec();58}5960static void unmarshal() throws Exception {61// Original document with all elements62Document doc = XMLUtils.string2doc("""63<?xml version="1.0" encoding="UTF-8"?>64<ds:Signature65xmlns:ds="http://www.w3.org/2000/09/xmldsig#"66xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"67xmlns:pss="http://www.w3.org/2007/05/xmldsig-more#">68<ds:SignedInfo>69<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments"/>70<ds:SignatureMethod Algorithm="http://www.w3.org/2007/05/xmldsig-more#rsa-pss">71<pss:RSAPSSParams>72<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/>73<pss:MaskGenerationFunction Algorithm="http://www.w3.org/2007/05/xmldsig-more#MGF1">74<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#sha384"/>75</pss:MaskGenerationFunction>76<pss:SaltLength>32</pss:SaltLength>77<pss:TrailerField>2</pss:TrailerField>78</pss:RSAPSSParams>79</ds:SignatureMethod>80<ds:Reference>81<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/>82<ds:DigestValue>abc=</ds:DigestValue>83</ds:Reference>84</ds:SignedInfo>85<ds:SignatureValue>abc=</ds:SignatureValue>86</ds:Signature>87""");8889// Unknown DigestMethod90Utils.runAndCheckException(91() -> getSpec(XMLUtils.withAttribute(doc, P2PSS + "/ds:DigestMethod", "Algorithm", "http://unknown")),92e -> Asserts.assertTrue(e instanceof MarshalException && e.getMessage().contains("Invalid digest algorithm"), e.getMessage()));93// Unknown MGF algorithm94Utils.runAndCheckException(95() -> getSpec(XMLUtils.withAttribute(doc, P2MGF, "Algorithm", "http://unknown")),96e -> Asserts.assertTrue(e instanceof MarshalException && e.getMessage().contains("Unknown MGF algorithm"), e.getMessage()));97// Unknown MGF DigestMethod98Utils.runAndCheckException(99() -> getSpec(XMLUtils.withAttribute(doc, P2MGF + "/ds:DigestMethod", "Algorithm", "http://unknown")),100e -> Asserts.assertTrue(e instanceof MarshalException && e.getMessage().contains("Invalid digest algorithm"), e.getMessage()));101// Invalid SaltLength102Utils.runAndCheckException(103() -> getSpec(XMLUtils.withText(doc, P2PSS + "/pss:SaltLength", "big")),104e -> Asserts.assertTrue(e instanceof MarshalException && e.getMessage().contains("Invalid salt length supplied"), e.getMessage()));105Utils.runAndCheckException(106() -> getSpec(XMLUtils.withText(doc, P2PSS + "/pss:SaltLength", "-1")),107e -> Asserts.assertTrue(e instanceof MarshalException && e.getMessage().contains("Invalid salt length supplied"), e.getMessage()));108// Invalid TrailerField109Utils.runAndCheckException(110() -> getSpec(XMLUtils.withText(doc, P2PSS + "/pss:TrailerField", "small")),111e -> Asserts.assertTrue(e instanceof MarshalException && e.getMessage().contains("Invalid trailer field supplied"), e.getMessage()));112Utils.runAndCheckException(113() -> getSpec(XMLUtils.withText(doc, P2PSS + "/pss:TrailerField", "-1")),114e -> Asserts.assertTrue(e instanceof MarshalException && e.getMessage().contains("Invalid trailer field supplied"), e.getMessage()));115116// Spec in original doc117checkSpec(doc, new PSSParameterSpec("SHA-512", "MGF1", new MGF1ParameterSpec("SHA-384"), 32, 2));118// Default MGF1 dm is same as PSS dm119checkSpec(XMLUtils.withoutNode(doc, P2MGF + "/ds:DigestMethod"), // No dm in MGF120new PSSParameterSpec("SHA-512", "MGF1", new MGF1ParameterSpec("SHA-512"), 32, 2));121checkSpec(XMLUtils.withoutNode(doc, P2MGF), // No MGF at all122new PSSParameterSpec("SHA-512", "MGF1", new MGF1ParameterSpec("SHA-512"), 32, 2));123// Default TrailerField is 1124checkSpec(XMLUtils.withoutNode(doc, P2PSS + "/pss:TrailerField"),125new PSSParameterSpec("SHA-512", "MGF1", new MGF1ParameterSpec("SHA-384"), 32, 1));126// Default SaltLength is dm's SaltLength127checkSpec(XMLUtils.withoutNode(doc, P2PSS + "/pss:SaltLength"),128new PSSParameterSpec("SHA-512", "MGF1", new MGF1ParameterSpec("SHA-384"), 64, 2));129// Default DigestMethod is 256130checkSpec(XMLUtils.withoutNode(doc, P2PSS + "/ds:DigestMethod"),131new PSSParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-384"), 32, 2));132// Default PSS is SHA-256133checkSpec(XMLUtils.withoutNode(doc, P2PSS), DEFAULT_SPEC);134}135136static void marshal() throws Exception {137var keyPairGenerator = KeyPairGenerator.getInstance("RSA");138var signer = XMLUtils.signer(keyPairGenerator.generateKeyPair().getPrivate());139PSSParameterSpec spec;140Document doc = XMLUtils.string2doc("<a>x</a>");141Document signedDoc;142143// Default sm. No need to describe at all144signer.sm(SignatureMethod.RSA_PSS, new RSAPSSParameterSpec(DEFAULT_SPEC));145signedDoc = signer.sign(doc);146Asserts.assertTrue(!XMLUtils.sub(signedDoc, P2SM).hasChildNodes());147148// Special salt.149spec = new PSSParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), 40, PSSParameterSpec.TRAILER_FIELD_BC);150signer.sm(SignatureMethod.RSA_PSS, new RSAPSSParameterSpec(spec));151signedDoc = signer.sign(doc);152Asserts.assertTrue(XMLUtils.sub(signedDoc, P2PSS + "/pss:SaltLength").getTextContent().equals("40"));153Asserts.assertTrue(XMLUtils.sub(signedDoc, P2MGF) == null);154Asserts.assertTrue(XMLUtils.sub(signedDoc, P2PSS + "/ds:DigestMethod") == null);155Asserts.assertTrue(XMLUtils.sub(signedDoc, P2PSS + "/pss:TrailerField") == null);156157// Different MGF1 dm158spec = new PSSParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-384"), 32, PSSParameterSpec.TRAILER_FIELD_BC);159signer.sm(SignatureMethod.RSA_PSS, new RSAPSSParameterSpec(spec));160signedDoc = signer.sign(doc);161Asserts.assertTrue(XMLUtils.sub(signedDoc, P2MGF + "/ds:DigestMethod").getAttribute("Algorithm").equals(DigestMethod.SHA384));162Asserts.assertTrue(XMLUtils.sub(signedDoc, P2PSS + "/ds:DigestMethod") == null);163Asserts.assertTrue(XMLUtils.sub(signedDoc, P2PSS + "/pss:SaltLength") == null);164Asserts.assertTrue(XMLUtils.sub(signedDoc, P2PSS + "/pss:TrailerField") == null);165166// Non default dm only167spec = new PSSParameterSpec("SHA-384", "MGF1", new MGF1ParameterSpec("SHA-384"), 48, PSSParameterSpec.TRAILER_FIELD_BC);168signer.sm(SignatureMethod.RSA_PSS, new RSAPSSParameterSpec(spec));169signedDoc = signer.sign(doc);170Asserts.assertTrue(XMLUtils.sub(signedDoc, P2PSS + "/ds:DigestMethod").getAttribute("Algorithm").equals(DigestMethod.SHA384));171Asserts.assertTrue(XMLUtils.sub(signedDoc, P2MGF) == null);172Asserts.assertTrue(XMLUtils.sub(signedDoc, P2PSS + "/pss:SaltLength") == null);173Asserts.assertTrue(XMLUtils.sub(signedDoc, P2PSS + "/pss:TrailerField") == null);174}175176static void spec() throws Exception {177XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");178SignatureMethod sm = fac.newSignatureMethod(SignatureMethod.RSA_PSS, null);179Asserts.assertTrue(equals(180((RSAPSSParameterSpec)sm.getParameterSpec()).getPSSParameterSpec(),181DEFAULT_SPEC));182183PSSParameterSpec special = new PSSParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-384"), 33, 2);184sm = fac.newSignatureMethod(SignatureMethod.RSA_PSS, new RSAPSSParameterSpec(special));185Asserts.assertTrue(equals(186((RSAPSSParameterSpec)sm.getParameterSpec()).getPSSParameterSpec(),187special));188}189190static PSSParameterSpec getSpec(Document doc) throws Exception {191var signatureNode = doc.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature").item(0);192DOMValidateContext valContext = new DOMValidateContext(new SecretKeySpec(new byte[1], "WHAT"), signatureNode);193valContext.setProperty("org.jcp.xml.dsig.secureValidation", false);194var signedInfo = XMLSignatureFactory.getInstance("DOM").unmarshalXMLSignature(valContext).getSignedInfo();195var spec = signedInfo.getSignatureMethod().getParameterSpec();196if (spec instanceof RSAPSSParameterSpec pspec) {197return pspec.getPSSParameterSpec();198} else {199Asserts.fail("Not PSSParameterSpec: " + spec.getClass());200return null;201}202}203204static void checkSpec(Document doc, PSSParameterSpec expected) throws Exception {205Asserts.assertTrue(equals(getSpec(doc), expected));206}207208static boolean equals(PSSParameterSpec p1, PSSParameterSpec p2) {209return p1.getDigestAlgorithm().equals(p2.getDigestAlgorithm())210&& p1.getSaltLength() == p2.getSaltLength()211&& p1.getTrailerField() == p2.getTrailerField()212&& p1.getMGFAlgorithm().equals(p2.getMGFAlgorithm())213&& ((MGF1ParameterSpec) p1.getMGFParameters()).getDigestAlgorithm()214.equals(((MGF1ParameterSpec) p2.getMGFParameters()).getDigestAlgorithm());215}216}217218219