diff options
Diffstat (limited to 'libraries/spongycastle/pg/src/main/java/org/spongycastle/openpgp/operator/PGPUtil.java')
-rw-r--r-- | libraries/spongycastle/pg/src/main/java/org/spongycastle/openpgp/operator/PGPUtil.java | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/libraries/spongycastle/pg/src/main/java/org/spongycastle/openpgp/operator/PGPUtil.java b/libraries/spongycastle/pg/src/main/java/org/spongycastle/openpgp/operator/PGPUtil.java new file mode 100644 index 000000000..a3e47b18a --- /dev/null +++ b/libraries/spongycastle/pg/src/main/java/org/spongycastle/openpgp/operator/PGPUtil.java @@ -0,0 +1,216 @@ +package org.spongycastle.openpgp.operator; + +import java.io.IOException; +import java.io.OutputStream; + +import org.spongycastle.bcpg.HashAlgorithmTags; +import org.spongycastle.bcpg.S2K; +import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; +import org.spongycastle.openpgp.PGPException; +import org.spongycastle.util.Strings; + +/** + * Basic utility class + */ +class PGPUtil + implements HashAlgorithmTags +{ + static byte[] makeKeyFromPassPhrase( + PGPDigestCalculator digestCalculator, + int algorithm, + S2K s2k, + char[] passPhrase) + throws PGPException + { + String algName = null; + int keySize = 0; + + switch (algorithm) + { + case SymmetricKeyAlgorithmTags.TRIPLE_DES: + keySize = 192; + algName = "DES_EDE"; + break; + case SymmetricKeyAlgorithmTags.IDEA: + keySize = 128; + algName = "IDEA"; + break; + case SymmetricKeyAlgorithmTags.CAST5: + keySize = 128; + algName = "CAST5"; + break; + case SymmetricKeyAlgorithmTags.BLOWFISH: + keySize = 128; + algName = "Blowfish"; + break; + case SymmetricKeyAlgorithmTags.SAFER: + keySize = 128; + algName = "SAFER"; + break; + case SymmetricKeyAlgorithmTags.DES: + keySize = 64; + algName = "DES"; + break; + case SymmetricKeyAlgorithmTags.AES_128: + keySize = 128; + algName = "AES"; + break; + case SymmetricKeyAlgorithmTags.AES_192: + keySize = 192; + algName = "AES"; + break; + case SymmetricKeyAlgorithmTags.AES_256: + keySize = 256; + algName = "AES"; + break; + case SymmetricKeyAlgorithmTags.TWOFISH: + keySize = 256; + algName = "Twofish"; + break; + default: + throw new PGPException("unknown symmetric algorithm: " + algorithm); + } + + byte[] pBytes = Strings.toUTF8ByteArray(passPhrase); + byte[] keyBytes = new byte[(keySize + 7) / 8]; + + int generatedBytes = 0; + int loopCount = 0; + + if (s2k != null) + { + if (s2k.getHashAlgorithm() != digestCalculator.getAlgorithm()) + { + throw new PGPException("s2k/digestCalculator mismatch"); + } + } + else + { + if (digestCalculator.getAlgorithm() != HashAlgorithmTags.MD5) + { + throw new PGPException("digestCalculator not for MD5"); + } + } + + OutputStream dOut = digestCalculator.getOutputStream(); + + try + { + while (generatedBytes < keyBytes.length) + { + if (s2k != null) + { + for (int i = 0; i != loopCount; i++) + { + dOut.write(0); + } + + byte[] iv = s2k.getIV(); + + switch (s2k.getType()) + { + case S2K.SIMPLE: + dOut.write(pBytes); + break; + case S2K.SALTED: + dOut.write(iv); + dOut.write(pBytes); + break; + case S2K.SALTED_AND_ITERATED: + long count = s2k.getIterationCount(); + dOut.write(iv); + dOut.write(pBytes); + + count -= iv.length + pBytes.length; + + while (count > 0) + { + if (count < iv.length) + { + dOut.write(iv, 0, (int)count); + break; + } + else + { + dOut.write(iv); + count -= iv.length; + } + + if (count < pBytes.length) + { + dOut.write(pBytes, 0, (int)count); + count = 0; + } + else + { + dOut.write(pBytes); + count -= pBytes.length; + } + } + break; + default: + throw new PGPException("unknown S2K type: " + s2k.getType()); + } + } + else + { + for (int i = 0; i != loopCount; i++) + { + dOut.write((byte)0); + } + + dOut.write(pBytes); + } + + dOut.close(); + + byte[] dig = digestCalculator.getDigest(); + + if (dig.length > (keyBytes.length - generatedBytes)) + { + System.arraycopy(dig, 0, keyBytes, generatedBytes, keyBytes.length - generatedBytes); + } + else + { + System.arraycopy(dig, 0, keyBytes, generatedBytes, dig.length); + } + + generatedBytes += dig.length; + + loopCount++; + } + } + catch (IOException e) + { + throw new PGPException("exception calculating digest: " + e.getMessage(), e); + } + + for (int i = 0; i != pBytes.length; i++) + { + pBytes[i] = 0; + } + + return keyBytes; + } + + public static byte[] makeKeyFromPassPhrase( + PGPDigestCalculatorProvider digCalcProvider, + int algorithm, + S2K s2k, + char[] passPhrase) + throws PGPException + { + PGPDigestCalculator digestCalculator; + + if (s2k != null) + { + digestCalculator = digCalcProvider.get(s2k.getHashAlgorithm()); + } + else + { + digestCalculator = digCalcProvider.get(HashAlgorithmTags.MD5); + } + + return makeKeyFromPassPhrase(digestCalculator, algorithm, s2k, passPhrase); + } +} |