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.DefaultJcaJceHelper; 14import org.bouncycastle.jcajce.NamedJcaJceHelper; 15import org.bouncycastle.jcajce.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 63 if (random != null) 64 { 65 sig.initSign(privateKey, random); 66 } 67 else 68 { 69 sig.initSign(privateKey); 70 } 71 72 return new ContentSigner() 73 { 74 private SignatureOutputStream stream = new SignatureOutputStream(sig); 75 76 public AlgorithmIdentifier getAlgorithmIdentifier() 77 { 78 return sigAlgId; 79 } 80 81 public OutputStream getOutputStream() 82 { 83 return stream; 84 } 85 86 public byte[] getSignature() 87 { 88 try 89 { 90 return stream.getSignature(); 91 } 92 catch (SignatureException e) 93 { 94 throw new RuntimeOperatorException("exception obtaining signature: " + e.getMessage(), e); 95 } 96 } 97 }; 98 } 99 catch (GeneralSecurityException e) 100 { 101 throw new OperatorCreationException("cannot create signer: " + e.getMessage(), e); 102 } 103 } 104 105 private class SignatureOutputStream 106 extends OutputStream 107 { 108 private Signature sig; 109 110 SignatureOutputStream(Signature sig) 111 { 112 this.sig = sig; 113 } 114 115 public void write(byte[] bytes, int off, int len) 116 throws IOException 117 { 118 try 119 { 120 sig.update(bytes, off, len); 121 } 122 catch (SignatureException e) 123 { 124 throw new OperatorStreamException("exception in content signer: " + e.getMessage(), e); 125 } 126 } 127 128 public void write(byte[] bytes) 129 throws IOException 130 { 131 try 132 { 133 sig.update(bytes); 134 } 135 catch (SignatureException e) 136 { 137 throw new OperatorStreamException("exception in content signer: " + e.getMessage(), e); 138 } 139 } 140 141 public void write(int b) 142 throws IOException 143 { 144 try 145 { 146 sig.update((byte)b); 147 } 148 catch (SignatureException e) 149 { 150 throw new OperatorStreamException("exception in content signer: " + e.getMessage(), e); 151 } 152 } 153 154 byte[] getSignature() 155 throws SignatureException 156 { 157 return sig.sign(); 158 } 159 } 160} 161