001 /** 002 * Copyright 2005-2011 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.rice.ksb.security; 017 018 import java.io.IOException; 019 import java.io.InputStream; 020 import java.security.GeneralSecurityException; 021 import java.security.Signature; 022 023 import javax.servlet.ServletInputStream; 024 025 /** 026 * An InputStream which decorates another InputStream with a wrapper that verifies the digital signature 027 * of the data after the last piece of data is read. The digital signature to verify against is 028 * passed into the constructor of this stream. 029 * 030 * @author Kuali Rice Team (rice.collab@kuali.org) 031 */ 032 public class SignatureVerifyingInputStream extends ServletInputStream { 033 034 private byte[] digitalSignature; 035 private Signature signature; 036 private InputStream wrappedInputStream; 037 038 public SignatureVerifyingInputStream(byte[] digitalSignature, Signature signature, InputStream wrappedInputStream) { 039 this.digitalSignature = digitalSignature; 040 this.signature = signature; 041 this.wrappedInputStream = wrappedInputStream; 042 } 043 044 @Override 045 public synchronized int read() throws IOException { 046 int data = this.wrappedInputStream.read(); 047 try { 048 if (data == -1) { 049 verifySignature(); 050 } else { 051 this.signature.update((byte)data); 052 } 053 } catch (GeneralSecurityException e) { 054 IOException exception = new IOException("Error processing digital signature."); 055 exception.initCause(e); 056 throw exception; 057 } 058 return data; 059 } 060 061 protected void verifySignature() throws IOException, GeneralSecurityException { 062 boolean verifies = this.signature.verify(this.digitalSignature); 063 if (!verifies) { 064 throw new IOException("The digital signature could not be successfully verified!"); 065 } 066 } 067 068 }