1 | /**************************************************************** |
2 | * Licensed to the Apache Software Foundation (ASF) under one * |
3 | * or more contributor license agreements. See the NOTICE file * |
4 | * distributed with this work for additional information * |
5 | * regarding copyright ownership. The ASF licenses this file * |
6 | * to you under the Apache License, Version 2.0 (the * |
7 | * "License"); you may not use this file except in compliance * |
8 | * with the License. You may obtain a copy of the License at * |
9 | * * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 * |
11 | * * |
12 | * Unless required by applicable law or agreed to in writing, * |
13 | * software distributed under the License is distributed on an * |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * |
15 | * KIND, either express or implied. See the License for the * |
16 | * specific language governing permissions and limitations * |
17 | * under the License. * |
18 | ****************************************************************/ |
19 | |
20 | package org.apache.james.jdkim.impl; |
21 | |
22 | import java.io.OutputStream; |
23 | import java.security.MessageDigest; |
24 | import java.security.NoSuchAlgorithmException; |
25 | |
26 | import org.apache.james.jdkim.api.BodyHasher; |
27 | import org.apache.james.jdkim.api.SignatureRecord; |
28 | import org.apache.james.jdkim.canon.DebugOutputStream; |
29 | import org.apache.james.jdkim.canon.DigestOutputStream; |
30 | import org.apache.james.jdkim.canon.LimitedOutputStream; |
31 | import org.apache.james.jdkim.canon.RelaxedBodyCanonicalizer; |
32 | import org.apache.james.jdkim.canon.SimpleBodyCanonicalizer; |
33 | import org.apache.james.jdkim.exceptions.PermFailException; |
34 | |
35 | public class BodyHasherImpl implements BodyHasher { |
36 | |
37 | private static final boolean DEEP_DEBUG = false; |
38 | private SignatureRecord sign; |
39 | private DigestOutputStream digesterOS; |
40 | private OutputStream out; |
41 | |
42 | public BodyHasherImpl(SignatureRecord sign) throws PermFailException { |
43 | MessageDigest md; |
44 | try { |
45 | md = MessageDigest.getInstance(sign.getHashAlgo().toString()); |
46 | } catch (NoSuchAlgorithmException e) { |
47 | throw new PermFailException("Unsupported algorythm: " |
48 | + sign.getHashAlgo(), e); |
49 | } |
50 | |
51 | int limit = sign.getBodyHashLimit(); |
52 | |
53 | // TODO enhance this to use a lookup service. |
54 | boolean relaxedBody = SignatureRecord.RELAXED.equals(sign |
55 | .getBodyCanonicalisationMethod()); |
56 | |
57 | if (!relaxedBody |
58 | && !SignatureRecord.SIMPLE.equals(sign |
59 | .getBodyCanonicalisationMethod())) { |
60 | throw new PermFailException( |
61 | "Unsupported body canonicalization method: " |
62 | + sign.getBodyCanonicalisationMethod()); |
63 | } |
64 | |
65 | DigestOutputStream dout = new DigestOutputStream(md); |
66 | |
67 | OutputStream out = dout; |
68 | if (DEEP_DEBUG) |
69 | out = new DebugOutputStream(out); |
70 | out = prepareCanonicalizerOutputStream(limit, relaxedBody, out); |
71 | |
72 | setSignatureRecord(sign); |
73 | setDigestOutputStream(dout); |
74 | setOutputStream(out); |
75 | } |
76 | |
77 | static OutputStream prepareCanonicalizerOutputStream(int limit, |
78 | boolean relaxedBody, OutputStream dout) { |
79 | OutputStream out = dout; |
80 | if (limit != -1) |
81 | out = new LimitedOutputStream(out, limit); |
82 | if (relaxedBody) |
83 | out = new RelaxedBodyCanonicalizer(out); |
84 | else |
85 | out = new SimpleBodyCanonicalizer(out); |
86 | return out; |
87 | } |
88 | |
89 | /** |
90 | * @see org.apache.james.jdkim.api.BodyHasher#getOutputStream() |
91 | */ |
92 | public OutputStream getOutputStream() { |
93 | return out; |
94 | } |
95 | |
96 | /** |
97 | * @see org.apache.james.jdkim.api.BodyHasher#getSignatureRecord() |
98 | */ |
99 | public SignatureRecord getSignatureRecord() { |
100 | return sign; |
101 | } |
102 | |
103 | private DigestOutputStream getDigesterOutputStream() { |
104 | return digesterOS; |
105 | } |
106 | |
107 | /** |
108 | * @see org.apache.james.jdkim.api.BodyHasher#getDigest() |
109 | */ |
110 | public byte[] getDigest() { |
111 | return getDigesterOutputStream().getDigest(); |
112 | } |
113 | |
114 | public void setSignatureRecord(SignatureRecord sign) { |
115 | this.sign = sign; |
116 | } |
117 | |
118 | public void setDigestOutputStream(DigestOutputStream dout) { |
119 | this.digesterOS = dout; |
120 | } |
121 | |
122 | public void setOutputStream(OutputStream out) { |
123 | this.out = out; |
124 | } |
125 | |
126 | } |