69 if (!(paramSpec instanceof PSSParameterSpec)) { |
63 if (!(paramSpec instanceof PSSParameterSpec)) { |
70 throw new InvalidParameterSpecException |
64 throw new InvalidParameterSpecException |
71 ("Inappropriate parameter specification"); |
65 ("Inappropriate parameter specification"); |
72 } |
66 } |
73 PSSParameterSpec spec = (PSSParameterSpec) paramSpec; |
67 PSSParameterSpec spec = (PSSParameterSpec) paramSpec; |
74 this.mdName = spec.getDigestAlgorithm(); |
68 |
75 String mgfName = spec.getMGFAlgorithm(); |
69 String mgfName = spec.getMGFAlgorithm(); |
76 if (!mgfName.equalsIgnoreCase("MGF1")) { |
70 if (!spec.getMGFAlgorithm().equalsIgnoreCase("MGF1")) { |
77 throw new InvalidParameterSpecException("Unsupported mgf " + |
71 throw new InvalidParameterSpecException("Unsupported mgf " + |
78 mgfName + "; MGF1 only"); |
72 mgfName + "; MGF1 only"); |
79 } |
73 } |
80 AlgorithmParameterSpec mgfSpec = spec.getMGFParameters(); |
74 AlgorithmParameterSpec mgfSpec = spec.getMGFParameters(); |
81 if (!(mgfSpec instanceof MGF1ParameterSpec)) { |
75 if (!(mgfSpec instanceof MGF1ParameterSpec)) { |
82 throw new InvalidParameterSpecException("Inappropriate mgf " + |
76 throw new InvalidParameterSpecException("Inappropriate mgf " + |
83 "parameters; non-null MGF1ParameterSpec only"); |
77 "parameters; non-null MGF1ParameterSpec only"); |
84 } |
78 } |
85 this.mgfSpec = (MGF1ParameterSpec) mgfSpec; |
79 this.spec = spec; |
86 this.saltLength = spec.getSaltLength(); |
|
87 this.trailerField = spec.getTrailerField(); |
|
88 } |
80 } |
89 |
81 |
90 @Override |
82 @Override |
91 protected void engineInit(byte[] encoded) throws IOException { |
83 protected void engineInit(byte[] encoded) throws IOException { |
92 // first initialize with the DEFAULT values before |
84 // first initialize with the DEFAULT values before |
93 // retrieving from the encoding bytes |
85 // retrieving from the encoding bytes |
94 this.mdName = DEFAULT.getDigestAlgorithm(); |
86 String mdName = DEFAULT.getDigestAlgorithm(); |
95 this.mgfSpec = (MGF1ParameterSpec) DEFAULT.getMGFParameters(); |
87 MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec) DEFAULT.getMGFParameters(); |
96 this.saltLength = DEFAULT.getSaltLength(); |
88 int saltLength = DEFAULT.getSaltLength(); |
97 this.trailerField = DEFAULT.getTrailerField(); |
89 int trailerField = DEFAULT.getTrailerField(); |
98 |
90 |
99 DerInputStream der = new DerInputStream(encoded); |
91 DerInputStream der = new DerInputStream(encoded); |
100 DerValue[] datum = der.getSequence(4); |
92 DerValue[] datum = der.getSequence(4); |
|
93 |
101 for (DerValue d : datum) { |
94 for (DerValue d : datum) { |
102 if (d.isContextSpecific((byte) 0x00)) { |
95 if (d.isContextSpecific((byte) 0x00)) { |
103 // hash algid |
96 // hash algid |
104 this.mdName = AlgorithmId.parse |
97 mdName = AlgorithmId.parse |
105 (d.data.getDerValue()).getName(); |
98 (d.data.getDerValue()).getName(); |
106 } else if (d.isContextSpecific((byte) 0x01)) { |
99 } else if (d.isContextSpecific((byte) 0x01)) { |
107 // mgf algid |
100 // mgf algid |
108 AlgorithmId val = AlgorithmId.parse(d.data.getDerValue()); |
101 AlgorithmId val = AlgorithmId.parse(d.data.getDerValue()); |
109 if (!val.getOID().equals(OID_MGF1)) { |
102 if (!val.getOID().equals(AlgorithmId.mgf1_oid)) { |
110 throw new IOException("Only MGF1 mgf is supported"); |
103 throw new IOException("Only MGF1 mgf is supported"); |
111 } |
104 } |
112 AlgorithmId params = AlgorithmId.parse( |
105 AlgorithmId params = AlgorithmId.parse( |
113 new DerValue(val.getEncodedParams())); |
106 new DerValue(val.getEncodedParams())); |
114 String mgfDigestName = params.getName(); |
107 String mgfDigestName = params.getName(); |
115 switch (mgfDigestName) { |
108 switch (mgfDigestName) { |
116 case "SHA-1": |
109 case "SHA-1": |
117 this.mgfSpec = MGF1ParameterSpec.SHA1; |
110 mgfSpec = MGF1ParameterSpec.SHA1; |
118 break; |
111 break; |
119 case "SHA-224": |
112 case "SHA-224": |
120 this.mgfSpec = MGF1ParameterSpec.SHA224; |
113 mgfSpec = MGF1ParameterSpec.SHA224; |
121 break; |
114 break; |
122 case "SHA-256": |
115 case "SHA-256": |
123 this.mgfSpec = MGF1ParameterSpec.SHA256; |
116 mgfSpec = MGF1ParameterSpec.SHA256; |
124 break; |
117 break; |
125 case "SHA-384": |
118 case "SHA-384": |
126 this.mgfSpec = MGF1ParameterSpec.SHA384; |
119 mgfSpec = MGF1ParameterSpec.SHA384; |
127 break; |
120 break; |
128 case "SHA-512": |
121 case "SHA-512": |
129 this.mgfSpec = MGF1ParameterSpec.SHA512; |
122 mgfSpec = MGF1ParameterSpec.SHA512; |
130 break; |
123 break; |
131 case "SHA-512/224": |
124 case "SHA-512/224": |
132 this.mgfSpec = MGF1ParameterSpec.SHA512_224; |
125 mgfSpec = MGF1ParameterSpec.SHA512_224; |
133 break; |
126 break; |
134 case "SHA-512/256": |
127 case "SHA-512/256": |
135 this.mgfSpec = MGF1ParameterSpec.SHA512_256; |
128 mgfSpec = MGF1ParameterSpec.SHA512_256; |
136 break; |
129 break; |
137 default: |
130 default: |
138 throw new IOException |
131 throw new IOException |
139 ("Unrecognized message digest algorithm " + |
132 ("Unrecognized message digest algorithm " + |
140 mgfDigestName); |
133 mgfDigestName); |
141 } |
134 } |
142 } else if (d.isContextSpecific((byte) 0x02)) { |
135 } else if (d.isContextSpecific((byte) 0x02)) { |
143 // salt length |
136 // salt length |
144 this.saltLength = d.data.getDerValue().getInteger(); |
137 saltLength = d.data.getDerValue().getInteger(); |
145 if (this.saltLength < 0) { |
138 if (saltLength < 0) { |
146 throw new IOException("Negative value for saltLength"); |
139 throw new IOException("Negative value for saltLength"); |
147 } |
140 } |
148 } else if (d.isContextSpecific((byte) 0x03)) { |
141 } else if (d.isContextSpecific((byte) 0x03)) { |
149 // trailer field |
142 // trailer field |
150 this.trailerField = d.data.getDerValue().getInteger(); |
143 trailerField = d.data.getDerValue().getInteger(); |
151 if (this.trailerField != 1) { |
144 if (trailerField != 1) { |
152 throw new IOException("Unsupported trailerField value " + |
145 throw new IOException("Unsupported trailerField value " + |
153 this.trailerField); |
146 trailerField); |
154 } |
147 } |
155 } else { |
148 } else { |
156 throw new IOException("Invalid encoded PSSParameters"); |
149 throw new IOException("Invalid encoded PSSParameters"); |
157 } |
150 } |
158 } |
151 } |
|
152 |
|
153 this.spec = new PSSParameterSpec(mdName, "MGF1", mgfSpec, |
|
154 saltLength, trailerField); |
159 } |
155 } |
160 |
156 |
161 @Override |
157 @Override |
162 protected void engineInit(byte[] encoded, String decodingMethod) |
158 protected void engineInit(byte[] encoded, String decodingMethod) |
163 throws IOException { |
159 throws IOException { |
171 @Override |
167 @Override |
172 protected <T extends AlgorithmParameterSpec> |
168 protected <T extends AlgorithmParameterSpec> |
173 T engineGetParameterSpec(Class<T> paramSpec) |
169 T engineGetParameterSpec(Class<T> paramSpec) |
174 throws InvalidParameterSpecException { |
170 throws InvalidParameterSpecException { |
175 if (PSSParameterSpec.class.isAssignableFrom(paramSpec)) { |
171 if (PSSParameterSpec.class.isAssignableFrom(paramSpec)) { |
176 return paramSpec.cast( |
172 return paramSpec.cast(spec); |
177 new PSSParameterSpec(mdName, "MGF1", mgfSpec, |
|
178 saltLength, trailerField)); |
|
179 } else { |
173 } else { |
180 throw new InvalidParameterSpecException |
174 throw new InvalidParameterSpecException |
181 ("Inappropriate parameter specification"); |
175 ("Inappropriate parameter specification"); |
182 } |
176 } |
183 } |
177 } |
184 |
178 |
185 @Override |
179 @Override |
186 protected byte[] engineGetEncoded() throws IOException { |
180 protected byte[] engineGetEncoded() throws IOException { |
|
181 return getEncoded(spec); |
|
182 } |
|
183 |
|
184 @Override |
|
185 protected byte[] engineGetEncoded(String encMethod) throws IOException { |
|
186 if ((encMethod != null) && |
|
187 (!encMethod.equalsIgnoreCase("ASN.1"))) { |
|
188 throw new IllegalArgumentException("Only support ASN.1 format"); |
|
189 } |
|
190 return engineGetEncoded(); |
|
191 } |
|
192 |
|
193 @Override |
|
194 protected String engineToString() { |
|
195 return spec.toString(); |
|
196 } |
|
197 |
|
198 /** |
|
199 * Returns the encoding of a {@link PSSParameterSpec} object. This method |
|
200 * is used in this class and {@link AlgorithmId}. |
|
201 * |
|
202 * @param spec a {@code PSSParameterSpec} object |
|
203 * @return its DER encoding |
|
204 * @throws IOException if the name of a MessageDigest or MaskGenAlgorithm |
|
205 * is unsupported |
|
206 */ |
|
207 public static byte[] getEncoded(PSSParameterSpec spec) throws IOException { |
|
208 |
|
209 AlgorithmParameterSpec mgfSpec = spec.getMGFParameters(); |
|
210 if (!(mgfSpec instanceof MGF1ParameterSpec)) { |
|
211 throw new IOException("Cannot encode " + mgfSpec); |
|
212 } |
|
213 |
|
214 MGF1ParameterSpec mgf1Spec = (MGF1ParameterSpec)mgfSpec; |
|
215 |
187 DerOutputStream tmp = new DerOutputStream(); |
216 DerOutputStream tmp = new DerOutputStream(); |
188 DerOutputStream tmp2, tmp3; |
217 DerOutputStream tmp2, tmp3; |
189 |
218 |
190 // MD |
219 // MD |
191 AlgorithmId mdAlgId; |
220 AlgorithmId mdAlgId; |
192 try { |
221 try { |
193 mdAlgId = AlgorithmId.get(mdName); |
222 mdAlgId = AlgorithmId.get(spec.getDigestAlgorithm()); |
194 } catch (NoSuchAlgorithmException nsae) { |
223 } catch (NoSuchAlgorithmException nsae) { |
195 throw new IOException("AlgorithmId " + mdName + |
224 throw new IOException("AlgorithmId " + spec.getDigestAlgorithm() + |
196 " impl not found"); |
225 " impl not found"); |
197 } |
226 } |
198 tmp2 = new DerOutputStream(); |
227 if (!mdAlgId.getOID().equals(AlgorithmId.SHA_oid)) { |
199 mdAlgId.derEncode(tmp2); |
228 tmp2 = new DerOutputStream(); |
200 tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0), |
229 mdAlgId.derEncode(tmp2); |
201 tmp2); |
230 tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0), |
|
231 tmp2); |
|
232 } |
202 |
233 |
203 // MGF |
234 // MGF |
204 tmp2 = new DerOutputStream(); |
|
205 tmp2.putOID(OID_MGF1); |
|
206 AlgorithmId mgfDigestId; |
235 AlgorithmId mgfDigestId; |
207 try { |
236 try { |
208 mgfDigestId = AlgorithmId.get(mgfSpec.getDigestAlgorithm()); |
237 mgfDigestId = AlgorithmId.get(mgf1Spec.getDigestAlgorithm()); |
209 } catch (NoSuchAlgorithmException nase) { |
238 } catch (NoSuchAlgorithmException nase) { |
210 throw new IOException("AlgorithmId " + |
239 throw new IOException("AlgorithmId " + |
211 mgfSpec.getDigestAlgorithm() + " impl not found"); |
240 mgf1Spec.getDigestAlgorithm() + " impl not found"); |
212 } |
241 } |
213 mgfDigestId.encode(tmp2); |
242 |
214 tmp3 = new DerOutputStream(); |
243 if (!mgfDigestId.getOID().equals(AlgorithmId.SHA_oid)) { |
215 tmp3.write(DerValue.tag_Sequence, tmp2); |
244 tmp2 = new DerOutputStream(); |
216 tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)1), |
245 tmp2.putOID(AlgorithmId.mgf1_oid); |
217 tmp3); |
246 mgfDigestId.encode(tmp2); |
|
247 tmp3 = new DerOutputStream(); |
|
248 tmp3.write(DerValue.tag_Sequence, tmp2); |
|
249 tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 1), |
|
250 tmp3); |
|
251 } |
218 |
252 |
219 // SaltLength |
253 // SaltLength |
220 tmp2 = new DerOutputStream(); |
254 if (spec.getSaltLength() != 20) { |
221 tmp2.putInteger(saltLength); |
255 tmp2 = new DerOutputStream(); |
222 tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)2), |
256 tmp2.putInteger(spec.getSaltLength()); |
223 tmp2); |
257 tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 2), |
|
258 tmp2); |
|
259 } |
224 |
260 |
225 // TrailerField |
261 // TrailerField |
226 tmp2 = new DerOutputStream(); |
262 if (spec.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) { |
227 tmp2.putInteger(trailerField); |
263 tmp2 = new DerOutputStream(); |
228 tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)3), |
264 tmp2.putInteger(spec.getTrailerField()); |
229 tmp2); |
265 tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 3), |
|
266 tmp2); |
|
267 } |
230 |
268 |
231 // Put all together under a SEQUENCE tag |
269 // Put all together under a SEQUENCE tag |
232 DerOutputStream out = new DerOutputStream(); |
270 DerOutputStream out = new DerOutputStream(); |
233 out.write(DerValue.tag_Sequence, tmp); |
271 out.write(DerValue.tag_Sequence, tmp); |
234 return out.toByteArray(); |
272 return out.toByteArray(); |
235 } |
273 } |
236 |
|
237 @Override |
|
238 protected byte[] engineGetEncoded(String encMethod) throws IOException { |
|
239 if ((encMethod != null) && |
|
240 (!encMethod.equalsIgnoreCase("ASN.1"))) { |
|
241 throw new IllegalArgumentException("Only support ASN.1 format"); |
|
242 } |
|
243 return engineGetEncoded(); |
|
244 } |
|
245 |
|
246 @Override |
|
247 protected String engineToString() { |
|
248 StringBuilder sb = new StringBuilder(); |
|
249 sb.append("MD: " + mdName + "\n") |
|
250 .append("MGF: MGF1" + mgfSpec.getDigestAlgorithm() + "\n") |
|
251 .append("SaltLength: " + saltLength + "\n") |
|
252 .append("TrailerField: " + trailerField + "\n"); |
|
253 return sb.toString(); |
|
254 } |
|
255 } |
274 } |