| BouncyCastleEncryptionProvider | Line # 34 | 54 | 25 | 100% |
1.0
|
| BouncyCastleEncryptionProvider.SecretKeyFactory | Line # 253 | 0 | 0 | - |
-1.0
|
| BouncyCastleEncryptionProvider.BCKeyFactory | Line # 258 | 2 | 2 | 100% |
1.0
|
| BouncyCastleEncryptionProvider.ValidatingSecretKeyFactory | Line # 275 | 6 | 3 | 100% |
1.0
|
| BouncyCastleEncryptionProvider.SecretKeyValidator | Line # 300 | 0 | 0 | - |
-1.0
|
| BouncyCastleEncryptionProvider.TransmissionValidator | Line # 308 | 6 | 3 | 100% |
1.0
|
| BouncyCastleEncryptionProvider.IllegalKeyException | Line # 325 | 2 | 1 | 0% |
0.0
|
| (34) | |||
| Result | |||
|
0.6086956
|
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testKnownAppProtocolVersion0
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testKnownAppProtocolVersion0
|
1 PASS | |
|
0.6086956
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProviderKeyPairGeneration.testCertificateLifecycle
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProviderKeyPairGeneration.testCertificateLifecycle
|
1 PASS | |
|
0.6086956
|
com.atlassian.security.auth.trustedapps.TestTrustedApplications.testExpiry
com.atlassian.security.auth.trustedapps.TestTrustedApplications.testExpiry
|
1 PASS | |
|
0.6086956
|
com.atlassian.security.auth.trustedapps.TestTrustedApplications.testRoundTrip
com.atlassian.security.auth.trustedapps.TestTrustedApplications.testRoundTrip
|
1 PASS | |
|
0.6086956
|
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testBadXForwardIp
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testBadXForwardIp
|
1 PASS | |
|
0.6086956
|
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testKnownAppProtocolVersion1
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testKnownAppProtocolVersion1
|
1 PASS | |
|
0.6086956
|
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testBadRequestIp
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testBadRequestIp
|
1 PASS | |
|
0.6086956
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProviderKeyPairGeneration.testFunnyUserName
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProviderKeyPairGeneration.testFunnyUserName
|
1 PASS | |
|
0.6086956
|
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testBadRequestUrl
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testBadRequestUrl
|
1 PASS | |
|
0.6086956
|
com.atlassian.security.auth.trustedapps.TestTrustedApplications.testNonExpiry
com.atlassian.security.auth.trustedapps.TestTrustedApplications.testNonExpiry
|
1 PASS | |
|
0.5869565
|
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testBadCertificate
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testBadCertificate
|
1 PASS | |
|
0.5217391
|
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testBadSecretKey
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testBadSecretKey
|
1 PASS | |
|
0.47826087
|
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testBadPublicKey
com.atlassian.security.auth.trustedapps.filter.TestTrustedApplicationsFilterAuthenticate.testBadPublicKey
|
1 PASS | |
|
0.23913044
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeNullMagicNumberVersion0
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeNullMagicNumberVersion0
|
1 PASS | |
|
0.23913044
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeSecretKey
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeSecretKey
|
1 PASS | |
|
0.23913044
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeNumberFormatException
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeNumberFormatException
|
1 PASS | |
|
0.2173913
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeInvalidCertificate
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeInvalidCertificate
|
1 PASS | |
|
0.1521739
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeBadSecretKey
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeBadSecretKey
|
1 PASS | |
|
0.11956522
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeNullMagicNumberVersion1
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeNullMagicNumberVersion1
|
1 PASS | |
|
0.10869565
|
com.atlassian.security.auth.trustedapps.TestDefaultTrustedApplication.testProductionCtorThrowsNullId
com.atlassian.security.auth.trustedapps.TestDefaultTrustedApplication.testProductionCtorThrowsNullId
|
1 PASS | |
|
0.10869565
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeBadMagicNumber
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testDecodeBadMagicNumber
|
1 PASS | |
|
0.10869565
|
com.atlassian.security.auth.trustedapps.TestDefaultTrustedApplication.testProductionCtorThrowsNullIpMatcher
com.atlassian.security.auth.trustedapps.TestDefaultTrustedApplication.testProductionCtorThrowsNullIpMatcher
|
1 PASS | |
|
0.10869565
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testValidatingSecretKeyFactory
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testValidatingSecretKeyFactory
|
1 PASS | |
|
0.10869565
|
com.atlassian.security.auth.trustedapps.TestDefaultTrustedApplication.testProductionCtorThrowsNullKey
com.atlassian.security.auth.trustedapps.TestDefaultTrustedApplication.testProductionCtorThrowsNullKey
|
1 PASS | |
|
0.10869565
|
com.atlassian.security.auth.trustedapps.TestDefaultTrustedApplication.testProductionCtor
com.atlassian.security.auth.trustedapps.TestDefaultTrustedApplication.testProductionCtor
|
1 PASS | |
|
0.10869565
|
com.atlassian.security.auth.trustedapps.TestDefaultTrustedApplication.testProductionCtorThrowsNullUrlMatcher
com.atlassian.security.auth.trustedapps.TestDefaultTrustedApplication.testProductionCtorThrowsNullUrlMatcher
|
1 PASS | |
|
0.07608695
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testSecretKeyValidatorInValidatesLeadingZero
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testSecretKeyValidatorInValidatesLeadingZero
|
1 PASS | |
|
0.07608695
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testSecretKeyValidatorValidatesLength16
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testSecretKeyValidatorValidatesLength16
|
1 PASS | |
|
0.054347824
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testSecretKeyValidatorInValidatesLengthGreaterThan16
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testSecretKeyValidatorInValidatesLengthGreaterThan16
|
1 PASS | |
|
0.054347824
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testSecretKeyValidatorInValidatesLengthLessThan16
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testSecretKeyValidatorInValidatesLengthLessThan16
|
1 PASS | |
|
0.04347826
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testGetApplicationCertificateReturnsProperly
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testGetApplicationCertificateReturnsProperly
|
1 PASS | |
|
0.04347826
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProviderKeyPairGeneration.testPublicKey
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProviderKeyPairGeneration.testPublicKey
|
1 PASS | |
|
0.04347826
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProviderKeyPairGeneration.testPrivateKey
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProviderKeyPairGeneration.testPrivateKey
|
1 PASS | |
|
0.032608695
|
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testBCSecretKeyFactory
com.atlassian.security.auth.trustedapps.TestBouncyCastleEncryptionProvider.testBCSecretKeyFactory
|
1 PASS | |
| 1 | package com.atlassian.security.auth.trustedapps; | |
| 2 | ||
| 3 | import com.atlassian.security.auth.trustedapps.Transcoder.Base64Transcoder; | |
| 4 | ||
| 5 | import org.bouncycastle.jce.provider.BouncyCastleProvider; | |
| 6 | ||
| 7 | import java.io.BufferedReader; | |
| 8 | import java.io.ByteArrayInputStream; | |
| 9 | import java.io.CharConversionException; | |
| 10 | import java.io.IOException; | |
| 11 | import java.io.InputStreamReader; | |
| 12 | import java.io.StringWriter; | |
| 13 | import java.security.InvalidKeyException; | |
| 14 | import java.security.KeyFactory; | |
| 15 | import java.security.KeyPair; | |
| 16 | import java.security.KeyPairGenerator; | |
| 17 | import java.security.NoSuchAlgorithmException; | |
| 18 | import java.security.NoSuchProviderException; | |
| 19 | import java.security.PrivateKey; | |
| 20 | import java.security.Provider; | |
| 21 | import java.security.PublicKey; | |
| 22 | import java.security.spec.InvalidKeySpecException; | |
| 23 | import java.security.spec.PKCS8EncodedKeySpec; | |
| 24 | import java.security.spec.X509EncodedKeySpec; | |
| 25 | ||
| 26 | import javax.crypto.BadPaddingException; | |
| 27 | import javax.crypto.Cipher; | |
| 28 | import javax.crypto.IllegalBlockSizeException; | |
| 29 | import javax.crypto.KeyGenerator; | |
| 30 | import javax.crypto.NoSuchPaddingException; | |
| 31 | import javax.crypto.SecretKey; | |
| 32 | import javax.crypto.spec.SecretKeySpec; | |
| 33 | ||
| 34 | public class BouncyCastleEncryptionProvider extends BaseEncryptionProvider | |
| 35 | { | |
| 36 | private static final Provider PROVIDER = new BouncyCastleProvider(); | |
| 37 | ||
| 38 | private static final String STREAM_CIPHER = "RC4"; | |
| 39 | private static final String ASYM_CIPHER = "RSA/NONE/NoPadding"; | |
| 40 | private static final String ASYM_ALGORITHM = "RSA"; | |
| 41 | ||
| 42 | private final SecretKeyFactory secretKeyFactory; | |
| 43 | private final Transcoder transcoder; | |
| 44 | ||
| 45 | 52 |
public BouncyCastleEncryptionProvider() |
| 46 | { | |
| 47 | 52 | this(new ValidatingSecretKeyFactory(new BCKeyFactory(), new TransmissionValidator()), new Base64Transcoder()); |
| 48 | } | |
| 49 | ||
| 50 | 52 |
private BouncyCastleEncryptionProvider(SecretKeyFactory secretKeyFactory, Transcoder transcoder) |
| 51 | { | |
| 52 | 52 | Null.not("secretKeyFactory", secretKeyFactory); |
| 53 | 52 | Null.not("transcoder", transcoder); |
| 54 | ||
| 55 | 52 | this.secretKeyFactory = secretKeyFactory; |
| 56 | 52 | this.transcoder = transcoder; |
| 57 | } | |
| 58 | ||
| 59 | /** | |
| 60 | * Decodes the given form into the real key object according to the given algorithm Uses Bouncy Castle as a provider | |
| 61 | * | |
| 62 | * @param encodedForm | |
| 63 | * the byte[] containing the key data | |
| 64 | * @return the generated PublicKey | |
| 65 | * @throws NoSuchAlgorithmException | |
| 66 | * @throws InvalidKeySpecException | |
| 67 | * @throws NoSuchProviderException | |
| 68 | */ | |
| 69 | 3 |
public PublicKey toPublicKey(byte[] encodedForm) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException |
| 70 | { | |
| 71 | 3 | final X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encodedForm); |
| 72 | 3 | final KeyFactory keyFactory = KeyFactory.getInstance(ASYM_ALGORITHM, PROVIDER); |
| 73 | 3 | return keyFactory.generatePublic(pubKeySpec); |
| 74 | } | |
| 75 | ||
| 76 | /** | |
| 77 | * Decodes the given form into the real key object according to the given algorithm Uses Bouncy Castle as a provider | |
| 78 | * | |
| 79 | * @param encodedForm | |
| 80 | * the PKS8 encoded key data | |
| 81 | * @return a fully formed PrivateKey | |
| 82 | * @throws NoSuchAlgorithmException | |
| 83 | * @throws InvalidKeySpecException | |
| 84 | * @throws NoSuchProviderException | |
| 85 | */ | |
| 86 | 2 |
public PrivateKey toPrivateKey(byte[] encodedForm) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException |
| 87 | { | |
| 88 | 2 | final PKCS8EncodedKeySpec pubKeySpec = new PKCS8EncodedKeySpec(encodedForm); |
| 89 | 2 | final KeyFactory keyFactory = KeyFactory.getInstance(ASYM_ALGORITHM, PROVIDER); |
| 90 | 2 | return keyFactory.generatePrivate(pubKeySpec); |
| 91 | } | |
| 92 | ||
| 93 | /** | |
| 94 | * Generates a new KeyPair. | |
| 95 | * <p> | |
| 96 | * Given algorithm name will be used to generate the key pair. It is mandatory. Security provides parameter is | |
| 97 | * optional and can be null in which case the choice of a provider is left to the VM. Key size is optional and can | |
| 98 | * be set to -1 in which case the default size is used. | |
| 99 | * | |
| 100 | * @throws NoSuchAlgorithmException | |
| 101 | * @throws NoSuchProviderException | |
| 102 | */ | |
| 103 | 17 |
public KeyPair generateNewKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException |
| 104 | { | |
| 105 | 17 | final KeyPairGenerator gen = KeyPairGenerator.getInstance(ASYM_ALGORITHM, PROVIDER); |
| 106 | 17 | return gen.generateKeyPair(); |
| 107 | } | |
| 108 | ||
| 109 | 22 |
public ApplicationCertificate decodeEncryptedCertificate(EncryptedCertificate encCert, PublicKey publicKey, String appId) throws InvalidCertificateException |
| 110 | { | |
| 111 | 22 | final BufferedReader in; |
| 112 | 22 | try |
| 113 | { | |
| 114 | 22 | final Cipher asymCipher = Cipher.getInstance(ASYM_CIPHER, PROVIDER); |
| 115 | 22 | asymCipher.init(Cipher.DECRYPT_MODE, publicKey); |
| 116 | ||
| 117 | /** | |
| 118 | * this should only happen with protocol version#1 or greater | |
| 119 | */ | |
| 120 | 22 | final String encryptedMagicNumber = encCert.getMagicNumber(); |
| 121 | 22 | if (encryptedMagicNumber != null) |
| 122 | { | |
| 123 | 18 | final String magicNumber = new String(asymCipher.doFinal(transcoder.decode(encryptedMagicNumber)), TrustedApplicationUtils.Constant.CHARSET_NAME); |
| 124 | 18 | TrustedApplicationUtils.validateMagicNumber("public key", appId, encCert.getProtocolVersion(), magicNumber); |
| 125 | } | |
| 126 | 4 | else if (encCert.getProtocolVersion() != null) |
| 127 | { | |
| 128 | 1 | throw new InvalidCertificateException(new TransportErrorMessage.BadMagicNumber("public key", appId)); |
| 129 | } | |
| 130 | ||
| 131 | 19 | final byte[] secretKeyData = asymCipher.doFinal(transcoder.decode(encCert.getSecretKey())); |
| 132 | 19 | final SecretKeySpec secretKeySpec = new SecretKeySpec(secretKeyData, STREAM_CIPHER); |
| 133 | ||
| 134 | 19 | final Cipher symCipher = Cipher.getInstance(STREAM_CIPHER, PROVIDER); |
| 135 | 19 | symCipher.init(Cipher.DECRYPT_MODE, secretKeySpec); |
| 136 | 17 | final byte[] decryptedData = symCipher.doFinal(transcoder.decode(encCert.getCertificate())); |
| 137 | 17 | in = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(decryptedData), TrustedApplicationUtils.Constant.CHARSET_NAME)); |
| 138 | } | |
| 139 | // ///CLOVER:OFF | |
| 140 | catch (NoSuchAlgorithmException e) | |
| 141 | { | |
| 142 | throw new AssertionError(e); | |
| 143 | } | |
| 144 | catch (NoSuchPaddingException e) | |
| 145 | { | |
| 146 | throw new AssertionError(e); | |
| 147 | } | |
| 148 | catch (NumberFormatException e) | |
| 149 | { | |
| 150 | throw new SystemException(appId, e); | |
| 151 | } | |
| 152 | catch (IllegalBlockSizeException e) | |
| 153 | { | |
| 154 | throw new SystemException(appId, e); | |
| 155 | } | |
| 156 | catch (BadPaddingException e) | |
| 157 | { | |
| 158 | throw new SystemException(appId, e); | |
| 159 | } | |
| 160 | catch (InvalidKeyException e) | |
| 161 | { | |
| 162 | throw new InvalidCertificateException(new TransportErrorMessage.BadMagicNumber("secret key", appId)); | |
| 163 | } | |
| 164 | catch (SecurityException e) | |
| 165 | { | |
| 166 | // this is here for Java 1.4 only where this exception is thrown when a bad secret key is encountered | |
| 167 | throw new InvalidCertificateException(new TransportErrorMessage.BadMagicNumber("secret key", appId)); | |
| 168 | } | |
| 169 | catch (IOException e) | |
| 170 | { | |
| 171 | throw new RuntimeException(e); | |
| 172 | } | |
| 173 | // /CLOVER:ON | |
| 174 | ||
| 175 | 17 | try |
| 176 | { | |
| 177 | 17 | final String created = in.readLine(); |
| 178 | 17 | final String userName = in.readLine(); |
| 179 | // validate the magic number before trying to parse the timestamp | |
| 180 | 17 | TrustedApplicationUtils.validateMagicNumber("secret key", appId, encCert.getProtocolVersion(), in.readLine()); |
| 181 | 15 | final long timeCreated = Long.parseLong(created); |
| 182 | ||
| 183 | 14 | return new DefaultApplicationCertificate(appId, userName, timeCreated); |
| 184 | } | |
| 185 | catch (NumberFormatException e) | |
| 186 | { | |
| 187 | 1 | throw new SystemException(appId, e); |
| 188 | } | |
| 189 | // ///CLOVER:OFF | |
| 190 | catch (CharConversionException e) | |
| 191 | { | |
| 192 | // only thrown under IBM JDK when unsupported utf8 chars are encountered | |
| 193 | throw new SystemException(appId, e); | |
| 194 | } | |
| 195 | catch (IOException e) | |
| 196 | { | |
| 197 | throw new RuntimeException(e); | |
| 198 | } | |
| 199 | // /CLOVER:ON | |
| 200 | } | |
| 201 | ||
| 202 | 13 |
public EncryptedCertificate createEncryptedCertificate(String userName, PrivateKey privateKey, String appId) |
| 203 | { | |
| 204 | 13 | try |
| 205 | { | |
| 206 | 13 | final SecretKey secretKey = secretKeyFactory.generateSecretKey(); |
| 207 | 13 | final Cipher symmetricCipher = Cipher.getInstance(STREAM_CIPHER, PROVIDER); |
| 208 | 13 | symmetricCipher.init(Cipher.ENCRYPT_MODE, secretKey); |
| 209 | ||
| 210 | 13 | final Cipher asymCipher = Cipher.getInstance(ASYM_CIPHER, PROVIDER); |
| 211 | 13 | asymCipher.init(Cipher.ENCRYPT_MODE, privateKey); |
| 212 | ||
| 213 | 13 | final String encryptedKey = transcoder.encode(asymCipher.doFinal(secretKey.getEncoded())); |
| 214 | 13 | final String encryptedMagic = transcoder.encode(asymCipher.doFinal(transcoder.getBytes(TrustedApplicationUtils.Constant.MAGIC))); |
| 215 | ||
| 216 | 13 | final StringWriter writer = new StringWriter(); |
| 217 | 13 | writer.write(String.valueOf(System.currentTimeMillis())); |
| 218 | 13 | writer.write('\n'); |
| 219 | 13 | writer.write(userName); |
| 220 | 13 | writer.write('\n'); |
| 221 | 13 | writer.write(TrustedApplicationUtils.Constant.MAGIC); |
| 222 | 13 | writer.flush(); |
| 223 | 13 | final byte[] encryptedData = symmetricCipher.doFinal(transcoder.getBytes(writer.toString())); |
| 224 | 13 | final String encodedData = transcoder.encode(encryptedData); |
| 225 | ||
| 226 | 13 | return new DefaultEncryptedCertificate(appId, encryptedKey, encodedData, TrustedApplicationUtils.Constant.VERSION, encryptedMagic); |
| 227 | } | |
| 228 | // ///CLOVER:OFF | |
| 229 | catch (NoSuchAlgorithmException e) | |
| 230 | { | |
| 231 | throw new AssertionError(e); | |
| 232 | } | |
| 233 | catch (NoSuchPaddingException e) | |
| 234 | { | |
| 235 | throw new AssertionError(e); | |
| 236 | } | |
| 237 | catch (InvalidKeyException e) | |
| 238 | { | |
| 239 | // only thrown under some JDKs, make it consistent | |
| 240 | throw new IllegalKeyException(e); | |
| 241 | } | |
| 242 | catch (IllegalBlockSizeException e) | |
| 243 | { | |
| 244 | throw new IllegalKeyException(e); | |
| 245 | } | |
| 246 | catch (BadPaddingException e) | |
| 247 | { | |
| 248 | throw new IllegalKeyException(e); | |
| 249 | } | |
| 250 | // /CLOVER:ON | |
| 251 | } | |
| 252 | ||
| 253 | interface SecretKeyFactory | |
| 254 | { | |
| 255 | SecretKey generateSecretKey(); | |
| 256 | } | |
| 257 | ||
| 258 | static class BCKeyFactory implements SecretKeyFactory | |
| 259 | { | |
| 260 | 14 |
public SecretKey generateSecretKey() |
| 261 | { | |
| 262 | 14 | try |
| 263 | { | |
| 264 | 14 | return KeyGenerator.getInstance(STREAM_CIPHER, PROVIDER).generateKey(); |
| 265 | } | |
| 266 | // /CLOVER:OFF | |
| 267 | catch (NoSuchAlgorithmException e) | |
| 268 | { | |
| 269 | throw new AssertionError(e); | |
| 270 | } | |
| 271 | // /CLOVER:ON | |
| 272 | } | |
| 273 | } | |
| 274 | ||
| 275 | static class ValidatingSecretKeyFactory implements SecretKeyFactory | |
| 276 | { | |
| 277 | private final SecretKeyFactory delegate; | |
| 278 | private final SecretKeyValidator validator; | |
| 279 | ||
| 280 | 53 |
ValidatingSecretKeyFactory(SecretKeyFactory secretKeyFactory, SecretKeyValidator validator) |
| 281 | { | |
| 282 | 53 | this.delegate = secretKeyFactory; |
| 283 | 53 | this.validator = validator; |
| 284 | } | |
| 285 | ||
| 286 | 14 |
public SecretKey generateSecretKey() |
| 287 | { | |
| 288 | 14 | SecretKey result = delegate.generateSecretKey(); |
| 289 | 18 | while (!validator.isValid(result)) |
| 290 | { | |
| 291 | 4 | result = delegate.generateSecretKey(); |
| 292 | } | |
| 293 | 14 | return result; |
| 294 | } | |
| 295 | } | |
| 296 | ||
| 297 | /** | |
| 298 | * check that a secret key is valid | |
| 299 | */ | |
| 300 | interface SecretKeyValidator | |
| 301 | { | |
| 302 | boolean isValid(SecretKey secretKey); | |
| 303 | } | |
| 304 | ||
| 305 | /** | |
| 306 | * leading zero's in the sevret key byte array lead to transmission problems | |
| 307 | */ | |
| 308 | static class TransmissionValidator implements SecretKeyValidator | |
| 309 | { | |
| 310 | 17 |
public boolean isValid(SecretKey secretKey) |
| 311 | { | |
| 312 | 17 | final byte[] encoded = secretKey.getEncoded(); |
| 313 | 17 | if (encoded.length != 16) |
| 314 | { | |
| 315 | 2 | return false; |
| 316 | } | |
| 317 | 15 | if (encoded[0] == 0) |
| 318 | { | |
| 319 | 1 | return false; |
| 320 | } | |
| 321 | 14 | return true; |
| 322 | } | |
| 323 | } | |
| 324 | ||
| 325 | static class IllegalKeyException extends IllegalArgumentException | |
| 326 | { | |
| 327 | 0 |
IllegalKeyException(Exception ex) |
| 328 | { | |
| 329 | 0 | super(ex.toString()); |
| 330 | 0 | this.initCause(ex); |
| 331 | } | |
| 332 | } | |
| 333 | } | |
|
||||||||||