1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45:
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55:
56: public final class AuthenticatedEntry
57: extends MaskableEnvelopeEntry
58: implements Registry
59: {
60: public static final int TYPE = 2;
61:
62: public AuthenticatedEntry(String mac, int macLen, Properties properties)
63: {
64: super(TYPE, properties);
65: if (macLen <= 0)
66: throw new IllegalArgumentException("invalid mac length");
67: this.properties.put("mac", mac);
68: this.properties.put("maclen", String.valueOf(macLen));
69: setMasked(false);
70: }
71:
72: private AuthenticatedEntry()
73: {
74: super(TYPE);
75: setMasked(true);
76: }
77:
78: public static AuthenticatedEntry decode(DataInputStream in)
79: throws IOException
80: {
81: AuthenticatedEntry entry = new AuthenticatedEntry();
82: entry.properties.decode(in);
83: if (! entry.properties.containsKey("mac"))
84: throw new MalformedKeyringException("no mac specified");
85: if (! entry.properties.containsKey("maclen"))
86: throw new MalformedKeyringException("no mac length specified");
87: return entry;
88: }
89:
90:
98: public void authenticate(byte[] key) throws IOException, InvalidKeyException
99: {
100: if (isMasked())
101: throw new IllegalStateException("entry is masked");
102: IMac m = getMac(key);
103: ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
104: MacOutputStream macout = new MacOutputStream(bout, m);
105: DataOutputStream out2 = new DataOutputStream(macout);
106: for (Iterator it = entries.iterator(); it.hasNext();)
107: {
108: Entry entry = (Entry) it.next();
109: entry.encode(out2);
110: }
111: bout.write(m.digest());
112: payload = bout.toByteArray();
113: }
114:
115:
122: public void verify(byte[] key) throws InvalidKeyException
123: {
124: if (! isMasked() || payload == null)
125: return;
126: IMac m = getMac(key);
127: m.update(payload, 0, payload.length - m.macSize());
128: byte[] macValue = new byte[m.macSize()];
129: System.arraycopy(payload, payload.length - macValue.length, macValue, 0,
130: macValue.length);
131: if (! Arrays.equals(macValue, m.digest()))
132: throw new IllegalArgumentException("MAC verification failed");
133: try
134: {
135: int len = payload.length - m.macSize();
136: ByteArrayInputStream bais = new ByteArrayInputStream(payload, 0, len);
137: DataInputStream in = new DataInputStream(bais);
138: decodeEnvelope(in);
139: }
140: catch (IOException ioe)
141: {
142: throw new IllegalArgumentException("malformed keyring fragment");
143: }
144: setMasked(false);
145: payload = null;
146: }
147:
148: protected void encodePayload() throws IOException
149: {
150: if (payload == null)
151: throw new IllegalStateException("not authenticated");
152: }
153:
154: private IMac getMac(byte[] key) throws InvalidKeyException
155: {
156: IMac mac = MacFactory.getInstance(properties.get("mac"));
157: if (mac == null)
158: throw new IllegalArgumentException("no such mac: " + properties.get("mac"));
159: int maclen = 0;
160: if (! properties.containsKey("maclen"))
161: throw new IllegalArgumentException("no MAC length");
162: try
163: {
164: maclen = Integer.parseInt(properties.get("maclen"));
165: }
166: catch (NumberFormatException nfe)
167: {
168: throw new IllegalArgumentException("bad MAC length");
169: }
170: HashMap macAttr = new HashMap();
171: macAttr.put(IMac.MAC_KEY_MATERIAL, key);
172: macAttr.put(IMac.TRUNCATED_SIZE, Integer.valueOf(maclen));
173: mac.init(macAttr);
174: return mac;
175: }
176: }