View Javadoc

1   /*
2    * #%L
3    * Bitrepository Protocol
4    * %%
5    * Copyright (C) 2010 - 2012 The State and University Library, The Royal Library and The State Archives, Denmark
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as 
9    * published by the Free Software Foundation, either version 2.1 of the 
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public 
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-2.1.html>.
20   * #L%
21   */
22  package org.bitrepository.protocol.security;
23  
24  import java.security.cert.X509Certificate;
25  
26  import org.bitrepository.protocol.security.exception.MessageAuthenticationException;
27  import org.bitrepository.protocol.security.exception.PermissionStoreException;
28  import org.bitrepository.protocol.security.exception.SecurityException;
29  import org.bouncycastle.cms.CMSException;
30  import org.bouncycastle.cms.CMSProcessableByteArray;
31  import org.bouncycastle.cms.CMSSignedData;
32  import org.bouncycastle.cms.SignerInformation;
33  import org.bouncycastle.cms.SignerInformationVerifier;
34  import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
35  import org.bouncycastle.operator.OperatorCreationException;
36  
37  /**
38   * Class to handle authentication of messages.  
39   */
40  public class BasicMessageAuthenticator implements MessageAuthenticator {
41  
42      /**
43       * Non-infrastructure certificates and permission store  
44       */
45      private final PermissionStore permissionStore;
46      
47      /**
48       * @param permissionStore the permissionStore holding the known certificates
49       */
50      public BasicMessageAuthenticator(PermissionStore permissionStore) {
51          this.permissionStore = permissionStore;
52      }
53      
54      /**
55       * Attempts to authenticate the message based on a signature. 
56       * @param messageData the data that is to be authenticated
57       * @param signatureData the signature that of the data to be authenticated.
58       * @throws MessageAuthenticationException in case authentication fails.  
59       */
60      @Override
61      public void authenticateMessage(byte[] messageData, byte[] signatureData) throws MessageAuthenticationException {
62          try {
63              CMSSignedData s = new CMSSignedData(new CMSProcessableByteArray(messageData), signatureData);
64              SignerInformation signer = (SignerInformation) s.getSignerInfos().getSigners().iterator().next();
65              X509Certificate signingCert = permissionStore.getCertificate(signer.getSID());
66              SignerInformationVerifier verifier = new JcaSimpleSignerInfoVerifierBuilder().setProvider(
67                      SecurityModuleConstants.BC).build(signingCert);
68              
69              if(!signer.verify(verifier)) {
70                  throw new MessageAuthenticationException("Signature does not match the message. Indicated " +
71                      "certificate did not sign message. Certificate issuer: " 
72                          + signingCert.getIssuerX500Principal().getName() + ", serial: " 
73                      + signingCert.getSerialNumber());  
74              }
75          } catch (PermissionStoreException e) {
76              throw new MessageAuthenticationException(e.getMessage(), e);
77          } catch (CMSException e) {
78              throw new SecurityException(e.getMessage(), e);
79          } catch (OperatorCreationException e) {
80              throw new SecurityException(e.getMessage(), e);
81          }
82      }
83  }