/** * Copyright 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.waveprotocol.box.server.waveserver; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.ProvisionException; import com.google.inject.Singleton; import com.google.inject.name.Named; import org.waveprotocol.wave.crypto.SignatureException; import org.waveprotocol.wave.crypto.SignerInfo; import org.waveprotocol.wave.crypto.WaveSigner; import org.waveprotocol.wave.crypto.WaveSignerFactory; import org.waveprotocol.wave.federation.FederationSettings; import org.waveprotocol.wave.federation.Proto.ProtocolSignature; import org.waveprotocol.wave.federation.Proto.ProtocolWaveletDelta; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.List; /** * A signature handler that delegates to a wave signer to sign deltas. */ public class SigningSignatureHandler implements SignatureHandler { /** * Guice {@link Provider} for the instance of {@link SigningSignatureHandler} */ @Singleton public static class SigningSignatureHandlerProvider implements Provider<SignatureHandler> { private static final FileOpener FILE_OPENER = new FileOpener(); private String privateKey; private List<String> certs; private String certDomain; private final WaveSignerFactory waveSignerFactory; private SigningSignatureHandler signer = null; /** * Public constructor. * @param privateKey file name that has the PKCS#8-PEM-encoded private key. * @param certs list of file names that have the certificates of this signer. * The first file name must have the signer's target certificate. The * certificates can be DER or PEM encoded. * @param certDomain the domain for which the certificate was issued. * @param factory A {@link WaveSignerFactory}. */ @Inject public SigningSignatureHandlerProvider( @Named(FederationSettings.CERTIFICATE_PRIVATE_KEY) String privateKey, @Named(FederationSettings.CERTIFICATE_FILES) List<String> certs, @Named(FederationSettings.CERTIFICATE_DOMAIN) String certDomain, WaveSignerFactory factory) { this.privateKey = privateKey; this.certs = certs; this.certDomain = certDomain; this.waveSignerFactory = factory; } @Override public SigningSignatureHandler get() { synchronized (this) { if (signer == null) { FileInputStream privateKeyStream; try { privateKeyStream = new FileInputStream(privateKey); } catch (FileNotFoundException e) { throw new ProvisionException("could not read private key", e); } Iterable<FileInputStream> certStreams = Iterables.transform(certs, FILE_OPENER); try { WaveSigner inner = waveSignerFactory.getSigner(privateKeyStream, certStreams, certDomain); signer = new SigningSignatureHandler(inner); } catch (SignatureException e) { throw new ProvisionException("could not make wave signer", e); } } } return signer; } // Function that turns file names into FileInputStreams private static class FileOpener implements Function<String, FileInputStream> { @Override public FileInputStream apply(String filename) { try { return new FileInputStream(filename); } catch (FileNotFoundException e) { throw new ProvisionException("could not read certificates", e); } } } } private final WaveSigner signer; public SigningSignatureHandler(WaveSigner signer) { this.signer = signer; } @Override public String getDomain() { return signer.getSignerInfo().getDomain(); } public SignerInfo getSignerInfo() { return signer.getSignerInfo(); } @Override public Iterable<ProtocolSignature> sign(ByteStringMessage<ProtocolWaveletDelta> delta) { return ImmutableList.of(signer.sign(delta.getByteString().toByteArray())); } }