下面列出了怎么用java.security.spec.PSSParameterSpec的API类实例代码及写法,或者点击链接到github查看源代码。
public static PSSParameterSpec getDefaultAlgorithmParameterSpec(
String sigAlg, PrivateKey k) {
if (sigAlg.equalsIgnoreCase("RSASSA-PSS")) {
switch (ifcFfcStrength(KeyUtil.getKeySize(k))) {
case "SHA256":
return PSSParamsHolder.PSS_256_SPEC;
case "SHA384":
return PSSParamsHolder.PSS_384_SPEC;
case "SHA512":
return PSSParamsHolder.PSS_512_SPEC;
default:
throw new AssertionError("Should not happen");
}
} else {
return null;
}
}
@Override
protected void engineInit(AlgorithmParameterSpec paramSpec)
throws InvalidParameterSpecException {
if (!(paramSpec instanceof PSSParameterSpec)) {
throw new InvalidParameterSpecException
("Inappropriate parameter specification");
}
PSSParameterSpec spec = (PSSParameterSpec) paramSpec;
String mgfName = spec.getMGFAlgorithm();
if (!spec.getMGFAlgorithm().equalsIgnoreCase("MGF1")) {
throw new InvalidParameterSpecException("Unsupported mgf " +
mgfName + "; MGF1 only");
}
AlgorithmParameterSpec mgfSpec = spec.getMGFParameters();
if (!(mgfSpec instanceof MGF1ParameterSpec)) {
throw new InvalidParameterSpecException("Inappropriate mgf " +
"parameters; non-null MGF1ParameterSpec only");
}
this.spec = spec;
}
@Override
protected void engineInit(AlgorithmParameterSpec paramSpec)
throws InvalidParameterSpecException {
if (!(paramSpec instanceof PSSParameterSpec)) {
throw new InvalidParameterSpecException
("Inappropriate parameter specification");
}
PSSParameterSpec spec = (PSSParameterSpec) paramSpec;
String mgfName = spec.getMGFAlgorithm();
if (!spec.getMGFAlgorithm().equalsIgnoreCase("MGF1")) {
throw new InvalidParameterSpecException("Unsupported mgf " +
mgfName + "; MGF1 only");
}
AlgorithmParameterSpec mgfSpec = spec.getMGFParameters();
if (!(mgfSpec instanceof MGF1ParameterSpec)) {
throw new InvalidParameterSpecException("Inappropriate mgf " +
"parameters; non-null MGF1ParameterSpec only");
}
this.spec = spec;
}
/**
* Returns an AlgorithmParameterSpec for generating a RSASSA-PSS key,
* which include the PSSParameters.
* Requires jdk11.
*
* @param keySizeInBits the size of the modulus in bits.
* @param sha the name of the hash function for hashing the input (e.g. "SHA-256")
* @param mgf the name of the mask generating function (typically "MGF1")
* @param mgfSha the name of the hash function for the mask generating function
* (typically the same as sha).
* @param saltLength the length of the salt in bytes (typically the digest size of sha,
* i.e. 32 for "SHA-256")
* @throws NoSuchMethodException if the AlgorithmParameterSpec is not
* supported (i.e. this happens before jdk11).
*/
public RSAKeyGenParameterSpec getPssAlgorithmParameters(
int keySizeInBits,
String sha,
String mgf,
String mgfSha,
int saltLength) throws Exception {
BigInteger publicExponent = new BigInteger("65537");
PSSParameterSpec params =
new PSSParameterSpec(sha, mgf, new MGF1ParameterSpec(mgfSha), saltLength, 1);
// Uses reflection to call
// public RSAKeyGenParameterSpec(int keysize, BigInteger publicExponent,
// AlgorithmParameterSpec keyParams)
// because this method is only supported in jdk11. This throws a NoSuchMethodException
// for older jdks.
Constructor<RSAKeyGenParameterSpec> c =
RSAKeyGenParameterSpec.class.getConstructor(
int.class, BigInteger.class, AlgorithmParameterSpec.class);
return c.newInstance(keySizeInBits, publicExponent, params);
}
@Override
protected void engineInit(AlgorithmParameterSpec paramSpec)
throws InvalidParameterSpecException {
if (!(paramSpec instanceof PSSParameterSpec)) {
throw new InvalidParameterSpecException
("Inappropriate parameter specification");
}
PSSParameterSpec spec = (PSSParameterSpec) paramSpec;
String mgfName = spec.getMGFAlgorithm();
if (!spec.getMGFAlgorithm().equalsIgnoreCase("MGF1")) {
throw new InvalidParameterSpecException("Unsupported mgf " +
mgfName + "; MGF1 only");
}
AlgorithmParameterSpec mgfSpec = spec.getMGFParameters();
if (!(mgfSpec instanceof MGF1ParameterSpec)) {
throw new InvalidParameterSpecException("Inappropriate mgf " +
"parameters; non-null MGF1ParameterSpec only");
}
this.spec = spec;
}
/**
* Return the PKCS#1 ASN.1 structure RSASSA-PSS-params.
*/
protected byte[] engineGetEncoded()
throws IOException
{
PSSParameterSpec pssSpec = currentSpec;
AlgorithmIdentifier hashAlgorithm = new AlgorithmIdentifier(
DigestFactory.getOID(pssSpec.getDigestAlgorithm()),
DERNull.INSTANCE);
MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec)pssSpec.getMGFParameters();
AlgorithmIdentifier maskGenAlgorithm = new AlgorithmIdentifier(
PKCSObjectIdentifiers.id_mgf1,
new AlgorithmIdentifier(DigestFactory.getOID(mgfSpec.getDigestAlgorithm()), DERNull.INSTANCE));
RSASSAPSSparams pssP = new RSASSAPSSparams(hashAlgorithm, maskGenAlgorithm, new ASN1Integer(pssSpec.getSaltLength()), new ASN1Integer(pssSpec.getTrailerField()));
return pssP.getEncoded("DER");
}
/**
* Return the PKCS#1 ASN.1 structure RSASSA-PSS-params.
*/
protected byte[] engineGetEncoded()
throws IOException
{
PSSParameterSpec pssSpec = currentSpec;
AlgorithmIdentifier hashAlgorithm = new AlgorithmIdentifier(
DigestFactory.getOID(pssSpec.getDigestAlgorithm()),
DERNull.INSTANCE);
MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec)pssSpec.getMGFParameters();
AlgorithmIdentifier maskGenAlgorithm = new AlgorithmIdentifier(
PKCSObjectIdentifiers.id_mgf1,
new AlgorithmIdentifier(DigestFactory.getOID(mgfSpec.getDigestAlgorithm()), DERNull.INSTANCE));
RSASSAPSSparams pssP = new RSASSAPSSparams(hashAlgorithm, maskGenAlgorithm, new ASN1Integer(pssSpec.getSaltLength()), new ASN1Integer(pssSpec.getTrailerField()));
return pssP.getEncoded("DER");
}
private static Pair<String, ? extends AlgorithmParameterSpec>
getSignatureAlgorithmJcaSignatureAlgorithm(int sigAlgorithm) {
switch (sigAlgorithm) {
case SIGNATURE_RSA_PSS_WITH_SHA256:
return Pair.create(
"SHA256withRSA/PSS",
new PSSParameterSpec(
"SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 256 / 8, 1));
case SIGNATURE_RSA_PSS_WITH_SHA512:
return Pair.create(
"SHA512withRSA/PSS",
new PSSParameterSpec(
"SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 512 / 8, 1));
case SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256:
return Pair.create("SHA256withRSA", null);
case SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512:
return Pair.create("SHA512withRSA", null);
case SIGNATURE_ECDSA_WITH_SHA256:
return Pair.create("SHA256withECDSA", null);
case SIGNATURE_ECDSA_WITH_SHA512:
return Pair.create("SHA512withECDSA", null);
case SIGNATURE_DSA_WITH_SHA256:
return Pair.create("SHA256withDSA", null);
default:
throw new IllegalArgumentException(
"Unknown signature algorithm: 0x"
+ Long.toHexString(sigAlgorithm & 0xffffffff));
}
}
@Override
protected <T extends AlgorithmParameterSpec>
T engineGetParameterSpec(Class<T> paramSpec)
throws InvalidParameterSpecException {
if (PSSParameterSpec.class.isAssignableFrom(paramSpec)) {
return paramSpec.cast(spec);
} else {
throw new InvalidParameterSpecException
("Inappropriate parameter specification");
}
}
static boolean test(String pg, String ps, String pv, PSSParameterSpec pss)
throws Exception {
KeyPairGenerator kpg = pg.length() == 1
? KeyPairGenerator.getInstance("RSA")
:KeyPairGenerator.getInstance("RSA", pg);
kpg.initialize(
pss.getDigestAlgorithm().equals("SHA-512") ? 2048: 1024,
NOT_SECURE_RANDOM);
KeyPair kp = kpg.generateKeyPair();
PrivateKey pr = kp.getPrivate();
PublicKey pu = kp.getPublic();
Signature s = ps.length() == 1
? Signature.getInstance("RSASSA-PSS")
: Signature.getInstance("RSASSA-PSS", ps);
s.initSign(pr);
s.setParameter(pss);
s.update(msg);
byte[] sig = s.sign();
Signature s2 = pv.length() == 1
? Signature.getInstance("RSASSA-PSS")
: Signature.getInstance("RSASSA-PSS", pv);
s2.initVerify(pu);
s2.setParameter(pss);
s2.update(msg);
return s2.verify(sig);
}
protected Signature createSignatureInstance() {
Signature sig = super.createSignatureInstance();
PSSParameterSpec spec = PSS_PARAMETER_SPECS.get(alg);
if (spec != null) {
setParameter(sig, spec);
}
return sig;
}
@Override
protected <T extends AlgorithmParameterSpec>
T engineGetParameterSpec(Class<T> paramSpec)
throws InvalidParameterSpecException {
if (PSSParameterSpec.class.isAssignableFrom(paramSpec)) {
return paramSpec.cast(spec);
} else {
throw new InvalidParameterSpecException
("Inappropriate parameter specification");
}
}
protected AlgorithmParameterSpec localEngineGetParameterSpec(
Class paramSpec)
throws InvalidParameterSpecException
{
if (paramSpec == PSSParameterSpec.class && currentSpec != null)
{
return currentSpec;
}
throw new InvalidParameterSpecException("unknown parameter spec passed to PSS parameters object.");
}
@Override
protected <T extends AlgorithmParameterSpec>
T engineGetParameterSpec(Class<T> paramSpec)
throws InvalidParameterSpecException {
if (PSSParameterSpec.class.isAssignableFrom(paramSpec)) {
return paramSpec.cast(spec);
} else {
throw new InvalidParameterSpecException
("Inappropriate parameter specification");
}
}
static boolean test(String pg, String ps, String pv, PSSParameterSpec pss)
throws Exception {
KeyPairGenerator kpg = pg.length() == 1
? KeyPairGenerator.getInstance("RSA")
:KeyPairGenerator.getInstance("RSA", pg);
kpg.initialize(
pss.getDigestAlgorithm().equals("SHA-512") ? 2048: 1024,
NOT_SECURE_RANDOM);
KeyPair kp = kpg.generateKeyPair();
PrivateKey pr = kp.getPrivate();
PublicKey pu = kp.getPublic();
Signature s = ps.length() == 1
? Signature.getInstance("RSASSA-PSS")
: Signature.getInstance("RSASSA-PSS", ps);
s.initSign(pr);
s.setParameter(pss);
s.update(msg);
byte[] sig = s.sign();
Signature s2 = pv.length() == 1
? Signature.getInstance("RSASSA-PSS")
: Signature.getInstance("RSASSA-PSS", pv);
s2.initVerify(pu);
s2.setParameter(pss);
s2.update(msg);
return s2.verify(sig);
}
public RsaPssSha256()
{
super(AlgorithmIdentifiers.RSA_PSS_USING_SHA256, "SHA256withRSAandMGF1");
MGF1ParameterSpec mgf1pec = MGF1ParameterSpec.SHA256;
PSSParameterSpec pssSpec = new PSSParameterSpec(mgf1pec.getDigestAlgorithm(), MGF1, mgf1pec, 32, TRAILER);
setAlgorithmParameterSpec(pssSpec);
}
public RsaPssSha384()
{
super(AlgorithmIdentifiers.RSA_PSS_USING_SHA384, "SHA384withRSAandMGF1");
MGF1ParameterSpec mgf1pec = MGF1ParameterSpec.SHA384;
PSSParameterSpec pssSpec = new PSSParameterSpec(mgf1pec.getDigestAlgorithm(), MGF1, mgf1pec, 48, TRAILER);
setAlgorithmParameterSpec(pssSpec);
}
@Test
public void rsaSsaPss() throws Exception {
final Algorithm algorithm = Algorithm.RSA_PSS;
final AlgorithmParameterSpec spec = new PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1);
final Signer signer = new Signer(privateKey,
new Signature("some-key-1", SigningAlgorithm.HS2019, algorithm, spec, null, Arrays.asList("date")));
final Signature signature = signer.sign(method, uri, headers);
// The RSASSA-PSS signature is non-deterministic, the value of the signature will be different
// every time a signature is generated.
final Verifier verifier = new Verifier(publicKey, signature);
boolean verifies = verifier.verify(method, uri, headers);
assertTrue(verifies);
}
/**
* Test #2 for <code>PSSParameterSpec(int)</code> ctor<br>
* Assertion:
* throws <code>IllegalArgumentException</code>
* if <code>saltLen</code> less than 0
*/
public final void testPSSParameterSpec0102() {
try {
new PSSParameterSpec(-1);
fail("Expected IAE not thrown");
} catch (IllegalArgumentException e) {
}
}
protected P11RSAPSSSignatureSpi(PSSParameterSpec baseParamSpec, boolean isRaw) {
this.originalSpec = baseParamSpec;
this.paramSpec = (baseParamSpec == null) ? PSSParameterSpec.DEFAULT : baseParamSpec;
this.mgfDigest = DigestFactory.getDigest(paramSpec.getDigestAlgorithm());
this.saltLength = paramSpec.getSaltLength();
this.trailer = getTrailer(paramSpec.getTrailerField());
this.isRaw = isRaw;
setupContentDigest();
}
protected AlgorithmParameterSpec localEngineGetParameterSpec(
Class paramSpec)
throws InvalidParameterSpecException
{
if (paramSpec == PSSParameterSpec.class && currentSpec != null)
{
return currentSpec;
}
throw new InvalidParameterSpecException("unknown parameter spec passed to PSS parameters object.");
}
protected void engineInit(
AlgorithmParameterSpec paramSpec)
throws InvalidParameterSpecException
{
if (!(paramSpec instanceof PSSParameterSpec))
{
throw new InvalidParameterSpecException("PSSParameterSpec required to initialise an PSS algorithm parameters object");
}
this.currentSpec = (PSSParameterSpec)paramSpec;
}
protected void engineInit(
AlgorithmParameterSpec paramSpec)
throws InvalidParameterSpecException
{
if (!(paramSpec instanceof PSSParameterSpec))
{
throw new InvalidParameterSpecException("PSSParameterSpec required to initialise an PSS algorithm parameters object");
}
this.currentSpec = (PSSParameterSpec)paramSpec;
}
protected Signature createSignatureInstance() {
Signature sig = super.createSignatureInstance();
PSSParameterSpec spec = PSS_PARAMETER_SPECS.get(alg);
if (spec != null) {
setParameter(sig, spec);
}
return sig;
}
protected void setParameter(Signature sig, PSSParameterSpec spec) {
try {
doSetParameter(sig, spec);
} catch (InvalidAlgorithmParameterException e) {
String msg = "Unsupported RSASSA-PSS parameter '" + spec + "': " + e.getMessage();
throw new SignatureException(msg, e);
}
}
public SHA224withRSA()
{
super(new RSABlindedEngine(), new PSSParameterSpec("SHA-224", "MGF1", new MGF1ParameterSpec("SHA-224"), 28, 1));
}
/**
* Utility method for checking the key PSS parameters against signature
* PSS parameters.
* Returns false if any of the digest/MGF algorithms and trailerField
* values does not match or if the salt length in key parameters is
* larger than the value in signature parameters.
*/
private static boolean isCompatible(AlgorithmParameterSpec keyParams,
PSSParameterSpec sigParams) {
if (keyParams == null) {
// key with null PSS parameters means no restriction
return true;
}
if (!(keyParams instanceof PSSParameterSpec)) {
return false;
}
// nothing to compare yet, defer the check to when sigParams is set
if (sigParams == null) {
return true;
}
PSSParameterSpec pssKeyParams = (PSSParameterSpec) keyParams;
// first check the salt length requirement
if (pssKeyParams.getSaltLength() > sigParams.getSaltLength()) {
return false;
}
// compare equality of the rest of fields based on DER encoding
PSSParameterSpec keyParams2 =
new PSSParameterSpec(pssKeyParams.getDigestAlgorithm(),
pssKeyParams.getMGFAlgorithm(),
pssKeyParams.getMGFParameters(),
sigParams.getSaltLength(),
pssKeyParams.getTrailerField());
PSSParameters ap = new PSSParameters();
// skip the JCA overhead
try {
ap.engineInit(keyParams2);
byte[] encoded = ap.engineGetEncoded();
ap.engineInit(sigParams);
byte[] encoded2 = ap.engineGetEncoded();
return Arrays.equals(encoded, encoded2);
} catch (Exception e) {
if (DEBUG) {
e.printStackTrace();
}
return false;
}
}
/**
* Validate the specified Signature PSS parameters.
*/
private PSSParameterSpec validateSigParams(AlgorithmParameterSpec p)
throws InvalidAlgorithmParameterException {
if (p == null) {
throw new InvalidAlgorithmParameterException
("Parameters cannot be null");
}
if (!(p instanceof PSSParameterSpec)) {
throw new InvalidAlgorithmParameterException
("parameters must be type PSSParameterSpec");
}
// no need to validate again if same as current signature parameters
PSSParameterSpec params = (PSSParameterSpec) p;
if (params == this.sigParams) return params;
RSAKey key = (this.privKey == null? this.pubKey : this.privKey);
// check against keyParams if set
if (key != null) {
if (!isCompatible(key.getParams(), params)) {
throw new InvalidAlgorithmParameterException
("Signature parameters does not match key parameters");
}
}
// now sanity check the parameter values
if (!(params.getMGFAlgorithm().equalsIgnoreCase("MGF1"))) {
throw new InvalidAlgorithmParameterException("Only supports MGF1");
}
if (params.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
throw new InvalidAlgorithmParameterException
("Only supports TrailerFieldBC(1)");
}
String digestAlgo = params.getDigestAlgorithm();
// check key length again
if (key != null) {
try {
int hLen = DIGEST_LENGTHS.get(digestAlgo);
checkKeyLength(key, hLen, params.getSaltLength());
} catch (SignatureException e) {
throw new InvalidAlgorithmParameterException(e);
}
}
return params;
}
@Override
protected void engineInit(byte[] encoded) throws IOException {
// first initialize with the DEFAULT values before
// retrieving from the encoding bytes
String mdName = DEFAULT.getDigestAlgorithm();
MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec) DEFAULT.getMGFParameters();
int saltLength = DEFAULT.getSaltLength();
int trailerField = DEFAULT.getTrailerField();
DerInputStream der = new DerInputStream(encoded);
DerValue[] datum = der.getSequence(4);
for (DerValue d : datum) {
if (d.isContextSpecific((byte) 0x00)) {
// hash algid
mdName = AlgorithmId.parse
(d.data.getDerValue()).getName();
} else if (d.isContextSpecific((byte) 0x01)) {
// mgf algid
AlgorithmId val = AlgorithmId.parse(d.data.getDerValue());
if (!val.getOID().equals(AlgorithmId.mgf1_oid)) {
throw new IOException("Only MGF1 mgf is supported");
}
AlgorithmId params = AlgorithmId.parse(
new DerValue(val.getEncodedParams()));
String mgfDigestName = params.getName();
switch (mgfDigestName) {
case "SHA-1":
mgfSpec = MGF1ParameterSpec.SHA1;
break;
case "SHA-224":
mgfSpec = MGF1ParameterSpec.SHA224;
break;
case "SHA-256":
mgfSpec = MGF1ParameterSpec.SHA256;
break;
case "SHA-384":
mgfSpec = MGF1ParameterSpec.SHA384;
break;
case "SHA-512":
mgfSpec = MGF1ParameterSpec.SHA512;
break;
case "SHA-512/224":
mgfSpec = MGF1ParameterSpec.SHA512_224;
break;
case "SHA-512/256":
mgfSpec = MGF1ParameterSpec.SHA512_256;
break;
default:
throw new IOException
("Unrecognized message digest algorithm " +
mgfDigestName);
}
} else if (d.isContextSpecific((byte) 0x02)) {
// salt length
saltLength = d.data.getDerValue().getInteger();
if (saltLength < 0) {
throw new IOException("Negative value for saltLength");
}
} else if (d.isContextSpecific((byte) 0x03)) {
// trailer field
trailerField = d.data.getDerValue().getInteger();
if (trailerField != 1) {
throw new IOException("Unsupported trailerField value " +
trailerField);
}
} else {
throw new IOException("Invalid encoded PSSParameters");
}
}
this.spec = new PSSParameterSpec(mdName, "MGF1", mgfSpec,
saltLength, trailerField);
}
/**
* Returns the encoding of a {@link PSSParameterSpec} object. This method
* is used in this class and {@link AlgorithmId}.
*
* @param spec a {@code PSSParameterSpec} object
* @return its DER encoding
* @throws IOException if the name of a MessageDigest or MaskGenAlgorithm
* is unsupported
*/
public static byte[] getEncoded(PSSParameterSpec spec) throws IOException {
AlgorithmParameterSpec mgfSpec = spec.getMGFParameters();
if (!(mgfSpec instanceof MGF1ParameterSpec)) {
throw new IOException("Cannot encode " + mgfSpec);
}
MGF1ParameterSpec mgf1Spec = (MGF1ParameterSpec)mgfSpec;
DerOutputStream tmp = new DerOutputStream();
DerOutputStream tmp2, tmp3;
// MD
AlgorithmId mdAlgId;
try {
mdAlgId = AlgorithmId.get(spec.getDigestAlgorithm());
} catch (NoSuchAlgorithmException nsae) {
throw new IOException("AlgorithmId " + spec.getDigestAlgorithm() +
" impl not found");
}
if (!mdAlgId.getOID().equals(AlgorithmId.SHA_oid)) {
tmp2 = new DerOutputStream();
mdAlgId.derEncode(tmp2);
tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0),
tmp2);
}
// MGF
AlgorithmId mgfDigestId;
try {
mgfDigestId = AlgorithmId.get(mgf1Spec.getDigestAlgorithm());
} catch (NoSuchAlgorithmException nase) {
throw new IOException("AlgorithmId " +
mgf1Spec.getDigestAlgorithm() + " impl not found");
}
if (!mgfDigestId.getOID().equals(AlgorithmId.SHA_oid)) {
tmp2 = new DerOutputStream();
tmp2.putOID(AlgorithmId.mgf1_oid);
mgfDigestId.encode(tmp2);
tmp3 = new DerOutputStream();
tmp3.write(DerValue.tag_Sequence, tmp2);
tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 1),
tmp3);
}
// SaltLength
if (spec.getSaltLength() != 20) {
tmp2 = new DerOutputStream();
tmp2.putInteger(spec.getSaltLength());
tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 2),
tmp2);
}
// TrailerField
if (spec.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
tmp2 = new DerOutputStream();
tmp2.putInteger(spec.getTrailerField());
tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 3),
tmp2);
}
// Put all together under a SEQUENCE tag
DerOutputStream out = new DerOutputStream();
out.write(DerValue.tag_Sequence, tmp);
return out.toByteArray();
}