1package org.bouncycastle.operator.jcajce; 2 3import java.io.IOException; 4import java.io.OutputStream; 5import java.security.GeneralSecurityException; 6import java.security.PrivateKey; 7import java.security.Provider; 8import java.security.SecureRandom; 9import java.security.Signature; 10import java.security.SignatureException; 11 12import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 13import org.bouncycastle.jcajce.util.DefaultJcaJceHelper; 14import org.bouncycastle.jcajce.util.NamedJcaJceHelper; 15import org.bouncycastle.jcajce.util.ProviderJcaJceHelper; 16import org.bouncycastle.operator.ContentSigner; 17import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; 18import org.bouncycastle.operator.OperatorCreationException; 19import org.bouncycastle.operator.OperatorStreamException; 20import org.bouncycastle.operator.RuntimeOperatorException; 21 22public class JcaContentSignerBuilder 23{ 24 private OperatorHelper helper = new OperatorHelper(new DefaultJcaJceHelper()); 25 private SecureRandom random; 26 private String signatureAlgorithm; 27 private AlgorithmIdentifier sigAlgId; 28 29 public JcaContentSignerBuilder(String signatureAlgorithm) 30 { 31 this.signatureAlgorithm = signatureAlgorithm; 32 this.sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find(signatureAlgorithm); 33 } 34 35 public JcaContentSignerBuilder setProvider(Provider provider) 36 { 37 this.helper = new OperatorHelper(new ProviderJcaJceHelper(provider)); 38 39 return this; 40 } 41 42 public JcaContentSignerBuilder setProvider(String providerName) 43 { 44 this.helper = new OperatorHelper(new NamedJcaJceHelper(providerName)); 45 46 return this; 47 } 48 49 public JcaContentSignerBuilder setSecureRandom(SecureRandom random) 50 { 51 this.random = random; 52 53 return this; 54 } 55 56 public ContentSigner build(PrivateKey privateKey) 57 throws OperatorCreationException 58 { 59 try 60 { 61 final Signature sig = helper.createSignature(sigAlgId); 62 final AlgorithmIdentifier signatureAlgId = sigAlgId; 63 64 if (random != null) 65 { 66 sig.initSign(privateKey, random); 67 } 68 else 69 { 70 sig.initSign(privateKey); 71 } 72 73 return new ContentSigner() 74 { 75 private SignatureOutputStream stream = new SignatureOutputStream(sig); 76 77 public AlgorithmIdentifier getAlgorithmIdentifier() 78 { 79 return signatureAlgId; 80 } 81 82 public OutputStream getOutputStream() 83 { 84 return stream; 85 } 86 87 public byte[] getSignature() 88 { 89 try 90 { 91 return stream.getSignature(); 92 } 93 catch (SignatureException e) 94 { 95 throw new RuntimeOperatorException("exception obtaining signature: " + e.getMessage(), e); 96 } 97 } 98 }; 99 } 100 catch (GeneralSecurityException e) 101 { 102 throw new OperatorCreationException("cannot create signer: " + e.getMessage(), e); 103 } 104 } 105 106 private class SignatureOutputStream 107 extends OutputStream 108 { 109 private Signature sig; 110 111 SignatureOutputStream(Signature sig) 112 { 113 this.sig = sig; 114 } 115 116 public void write(byte[] bytes, int off, int len) 117 throws IOException 118 { 119 try 120 { 121 sig.update(bytes, off, len); 122 } 123 catch (SignatureException e) 124 { 125 throw new OperatorStreamException("exception in content signer: " + e.getMessage(), e); 126 } 127 } 128 129 public void write(byte[] bytes) 130 throws IOException 131 { 132 try 133 { 134 sig.update(bytes); 135 } 136 catch (SignatureException e) 137 { 138 throw new OperatorStreamException("exception in content signer: " + e.getMessage(), e); 139 } 140 } 141 142 public void write(int b) 143 throws IOException 144 { 145 try 146 { 147 sig.update((byte)b); 148 } 149 catch (SignatureException e) 150 { 151 throw new OperatorStreamException("exception in content signer: " + e.getMessage(), e); 152 } 153 } 154 155 byte[] getSignature() 156 throws SignatureException 157 { 158 return sig.sign(); 159 } 160 } 161} 162