001: package org.bouncycastle.jce.provider;
002:
003: import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
004: import org.bouncycastle.crypto.AsymmetricBlockCipher;
005: import org.bouncycastle.crypto.CryptoException;
006: import org.bouncycastle.crypto.Digest;
007: import org.bouncycastle.crypto.engines.RSABlindedEngine;
008: import org.bouncycastle.crypto.params.ParametersWithRandom;
009: import org.bouncycastle.crypto.signers.PSSSigner;
010:
011: import java.security.AlgorithmParameters;
012: import java.security.InvalidKeyException;
013: import java.security.InvalidParameterException;
014: import java.security.PrivateKey;
015: import java.security.PublicKey;
016: import java.security.SecureRandom;
017: import java.security.Signature;
018: import java.security.SignatureException;
019: import java.security.interfaces.RSAPrivateKey;
020: import java.security.interfaces.RSAPublicKey;
021: import java.security.spec.AlgorithmParameterSpec;
022: import java.security.spec.MGF1ParameterSpec;
023: import java.security.spec.PSSParameterSpec;
024:
025: public class JDKPSSSigner extends Signature {
026: private AlgorithmParameters engineParams;
027: private PSSParameterSpec paramSpec;
028: private PSSParameterSpec originalSpec;
029: private AsymmetricBlockCipher signer;
030: private Digest digest;
031: private int saltLength;
032: private byte trailer;
033:
034: private PSSSigner pss;
035:
036: private byte getTrailer(int trailerField) {
037: if (trailerField == 1) {
038: return PSSSigner.TRAILER_IMPLICIT;
039: }
040:
041: throw new IllegalArgumentException("unknown trailer field");
042: }
043:
044: protected JDKPSSSigner(String name, AsymmetricBlockCipher signer,
045: PSSParameterSpec paramSpec) {
046: super (name);
047:
048: this .signer = signer;
049:
050: if (paramSpec == null) {
051: originalSpec = null;
052: paramSpec = PSSParameterSpec.DEFAULT;
053: } else {
054: originalSpec = paramSpec;
055: this .paramSpec = paramSpec;
056: }
057:
058: this .digest = JCEDigestUtil.getDigest(paramSpec
059: .getDigestAlgorithm());
060: this .saltLength = paramSpec.getSaltLength();
061: this .trailer = getTrailer(paramSpec.getTrailerField());
062: }
063:
064: protected void engineInitVerify(PublicKey publicKey)
065: throws InvalidKeyException {
066: if (!(publicKey instanceof RSAPublicKey)) {
067: throw new InvalidKeyException(
068: "Supplied key is not a RSAPublicKey instance");
069: }
070:
071: pss = new PSSSigner(signer, digest, saltLength);
072: pss.init(false, RSAUtil
073: .generatePublicKeyParameter((RSAPublicKey) publicKey));
074: }
075:
076: protected void engineInitSign(PrivateKey privateKey,
077: SecureRandom random) throws InvalidKeyException {
078: if (!(privateKey instanceof RSAPrivateKey)) {
079: throw new InvalidKeyException(
080: "Supplied key is not a RSAPrivateKey instance");
081: }
082:
083: pss = new PSSSigner(signer, digest, saltLength, trailer);
084: pss
085: .init(
086: true,
087: new ParametersWithRandom(
088: RSAUtil
089: .generatePrivateKeyParameter((RSAPrivateKey) privateKey),
090: random));
091: }
092:
093: protected void engineInitSign(PrivateKey privateKey)
094: throws InvalidKeyException {
095: if (!(privateKey instanceof RSAPrivateKey)) {
096: throw new InvalidKeyException(
097: "Supplied key is not a RSAPrivateKey instance");
098: }
099:
100: pss = new PSSSigner(signer, digest, saltLength, trailer);
101: pss
102: .init(
103: true,
104: RSAUtil
105: .generatePrivateKeyParameter((RSAPrivateKey) privateKey));
106: }
107:
108: protected void engineUpdate(byte b) throws SignatureException {
109: pss.update(b);
110: }
111:
112: protected void engineUpdate(byte[] b, int off, int len)
113: throws SignatureException {
114: pss.update(b, off, len);
115: }
116:
117: protected byte[] engineSign() throws SignatureException {
118: try {
119: return pss.generateSignature();
120: } catch (CryptoException e) {
121: throw new SignatureException(e.getMessage());
122: }
123: }
124:
125: protected boolean engineVerify(byte[] sigBytes)
126: throws SignatureException {
127: return pss.verifySignature(sigBytes);
128: }
129:
130: protected void engineSetParameter(AlgorithmParameterSpec params)
131: throws InvalidParameterException {
132: if (params instanceof PSSParameterSpec) {
133: paramSpec = (PSSParameterSpec) params;
134:
135: if (originalSpec != null) {
136: if (!JCEDigestUtil.isSameDigest(originalSpec
137: .getDigestAlgorithm(), paramSpec
138: .getDigestAlgorithm())) {
139: throw new InvalidParameterException(
140: "parameter must be using "
141: + originalSpec.getDigestAlgorithm());
142: }
143: }
144: if (!paramSpec.getMGFAlgorithm().equalsIgnoreCase("MGF1")
145: && !paramSpec.getMGFAlgorithm().equals(
146: PKCSObjectIdentifiers.id_mgf1.getId())) {
147: throw new InvalidParameterException(
148: "unknown mask generation function specified");
149: }
150:
151: if (!(paramSpec.getMGFParameters() instanceof MGF1ParameterSpec)) {
152: throw new InvalidParameterException(
153: "unkown MGF parameters");
154: }
155:
156: MGF1ParameterSpec mgfParams = (MGF1ParameterSpec) paramSpec
157: .getMGFParameters();
158:
159: if (!JCEDigestUtil.isSameDigest(mgfParams
160: .getDigestAlgorithm(), paramSpec
161: .getDigestAlgorithm())) {
162: throw new InvalidParameterException(
163: "digest algorithm for MGF should be the same as for PSS parameters.");
164: }
165:
166: digest = JCEDigestUtil.getDigest(mgfParams
167: .getDigestAlgorithm());
168:
169: if (digest == null) {
170: throw new InvalidParameterException(
171: "no match on MGF digest algorithm: "
172: + mgfParams.getDigestAlgorithm());
173: }
174:
175: this .saltLength = paramSpec.getSaltLength();
176: this .trailer = getTrailer(paramSpec.getTrailerField());
177: } else {
178: throw new InvalidParameterException(
179: "Only PSSParameterSpec supported");
180: }
181: }
182:
183: protected AlgorithmParameters engineGetParameters() {
184: if (engineParams == null) {
185: if (paramSpec != null) {
186: try {
187: engineParams = AlgorithmParameters.getInstance(
188: "PSS", "BC");
189: engineParams.init(paramSpec);
190: } catch (Exception e) {
191: throw new RuntimeException(e.toString());
192: }
193: }
194: }
195:
196: return engineParams;
197: }
198:
199: /**
200: * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)">
201: */
202: protected void engineSetParameter(String param, Object value) {
203: throw new UnsupportedOperationException(
204: "engineSetParameter unsupported");
205: }
206:
207: protected Object engineGetParameter(String param) {
208: throw new UnsupportedOperationException(
209: "engineGetParameter unsupported");
210: }
211:
212: static public class PSSwithRSA extends JDKPSSSigner {
213: public PSSwithRSA() {
214: super ("SHA1withRSAandMGF1", new RSABlindedEngine(), null);
215: }
216: }
217:
218: static public class SHA1withRSA extends JDKPSSSigner {
219: public SHA1withRSA() {
220: super ("SHA1withRSAandMGF1", new RSABlindedEngine(),
221: PSSParameterSpec.DEFAULT);
222: }
223: }
224:
225: static public class SHA224withRSA extends JDKPSSSigner {
226: public SHA224withRSA() {
227: super ("SHA224withRSAandMGF1", new RSABlindedEngine(),
228: new PSSParameterSpec("SHA-224", "MGF1",
229: new MGF1ParameterSpec("SHA-224"), 28, 1));
230: }
231: }
232:
233: static public class SHA256withRSA extends JDKPSSSigner {
234: public SHA256withRSA() {
235: super ("SHA256withRSAandMGF1", new RSABlindedEngine(),
236: new PSSParameterSpec("SHA-256", "MGF1",
237: new MGF1ParameterSpec("SHA-256"), 32, 1));
238: }
239: }
240:
241: static public class SHA384withRSA extends JDKPSSSigner {
242: public SHA384withRSA() {
243: super ("SHA384withRSAandMGF1", new RSABlindedEngine(),
244: new PSSParameterSpec("SHA-384", "MGF1",
245: new MGF1ParameterSpec("SHA-384"), 48, 1));
246: }
247: }
248:
249: static public class SHA512withRSA extends JDKPSSSigner {
250: public SHA512withRSA() {
251: super ("SHA512withRSAandMGF1", new RSABlindedEngine(),
252: new PSSParameterSpec("SHA-512", "MGF1",
253: new MGF1ParameterSpec("SHA-512"), 64, 1));
254: }
255: }
256: }
|