PageRenderTime 48ms CodeModel.GetById 38ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/projects/azureus-4.7.0.2/org/bouncycastle/openssl/PEMUtilities.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 185 lines | 163 code | 15 blank | 7 comment | 27 complexity | cc7efb74ed55347e229bed884d94d7a4 MD5 | raw file
  1package org.bouncycastle.openssl;
  2
  3import org.bouncycastle.crypto.PBEParametersGenerator;
  4import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
  5import org.bouncycastle.crypto.params.KeyParameter;
  6
  7import javax.crypto.Cipher;
  8import javax.crypto.SecretKey;
  9import javax.crypto.spec.IvParameterSpec;
 10import javax.crypto.spec.RC2ParameterSpec;
 11import java.io.IOException;
 12import java.security.Key;
 13import java.security.spec.AlgorithmParameterSpec;
 14
 15final class PEMUtilities
 16{
 17    static byte[] crypt(
 18        boolean encrypt,
 19        String  provider,
 20        byte[]  bytes,
 21        char[]  password,
 22        String  dekAlgName,
 23        byte[]  iv)
 24        throws IOException
 25    {
 26        AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
 27        String                 alg;
 28        String                 blockMode = "CBC";
 29        String                 padding = "PKCS5Padding";
 30        Key                    sKey;
 31
 32
 33        // Figure out block mode and padding.
 34        if (dekAlgName.endsWith("-CFB"))
 35        {
 36            blockMode = "CFB";
 37            padding = "NoPadding";
 38        }
 39        if (dekAlgName.endsWith("-ECB") ||
 40            "DES-EDE".equals(dekAlgName) ||
 41            "DES-EDE3".equals(dekAlgName))
 42        {
 43            // ECB is actually the default (though seldom used) when OpenSSL
 44            // uses DES-EDE (des2) or DES-EDE3 (des3).
 45            blockMode = "ECB";
 46            paramSpec = null;
 47        }
 48        if (dekAlgName.endsWith("-OFB"))
 49        {
 50            blockMode = "OFB";
 51            padding = "NoPadding";
 52        }
 53
 54
 55        // Figure out algorithm and key size.
 56        if (dekAlgName.startsWith("DES-EDE"))
 57        {
 58            alg = "DESede";
 59            // "DES-EDE" is actually des2 in OpenSSL-speak!
 60            // "DES-EDE3" is des3.
 61            boolean des2 = !dekAlgName.startsWith("DES-EDE3");
 62            sKey = getKey(password, alg, 24, iv, des2);
 63        }
 64        else if (dekAlgName.startsWith("DES-"))
 65        {
 66            alg = "DES";
 67            sKey = getKey(password, alg, 8, iv);
 68        }
 69        else if (dekAlgName.startsWith("BF-"))
 70        {
 71            alg = "Blowfish";
 72            sKey = getKey(password, alg, 16, iv);
 73        }
 74        else if (dekAlgName.startsWith("RC2-"))
 75        {
 76            alg = "RC2";
 77            int keyBits = 128;
 78            if (dekAlgName.startsWith("RC2-40-"))
 79            {
 80                keyBits = 40;
 81            }
 82            else if (dekAlgName.startsWith("RC2-64-"))
 83            {
 84                keyBits = 64;
 85            }
 86            sKey = getKey(password, alg, keyBits / 8, iv);
 87            if (paramSpec == null) // ECB block mode
 88            {
 89                paramSpec = new RC2ParameterSpec(keyBits);
 90            }
 91            else
 92            {
 93                paramSpec = new RC2ParameterSpec(keyBits, iv);
 94            }
 95        }
 96        else if (dekAlgName.startsWith("AES-"))
 97        {
 98            alg = "AES";
 99            byte[] salt = iv;
100            if (salt.length > 8)
101            {
102                salt = new byte[8];
103                System.arraycopy(iv, 0, salt, 0, 8);
104            }
105
106            int keyBits;
107            if (dekAlgName.startsWith("AES-128-"))
108            {
109                keyBits = 128;
110            }
111            else if (dekAlgName.startsWith("AES-192-"))
112            {
113                keyBits = 192;
114            }
115            else if (dekAlgName.startsWith("AES-256-"))
116            {
117                keyBits = 256;
118            }
119            else
120            {
121                throw new IOException("unknown AES encryption with private key");
122            }
123            sKey = getKey(password, "AES", keyBits / 8, salt);
124        }
125        else
126        {
127            throw new IOException("unknown encryption with private key");
128        }
129
130        String transformation = alg + "/" + blockMode + "/" + padding;
131
132        try
133        {
134            Cipher c = Cipher.getInstance(transformation, provider);
135            int    mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
136
137            if (paramSpec == null) // ECB block mode
138            {
139                c.init(mode, sKey);
140            }
141            else
142            {
143                c.init(mode, sKey, paramSpec);
144            }
145            return c.doFinal(bytes);
146        }
147        catch (Exception e)
148        {
149            throw new IOException("exception using cipher: " + e.toString());
150        }
151    }
152
153    private static SecretKey getKey(
154        char[]  password,
155        String  algorithm,
156        int     keyLength,
157        byte[]  salt)
158        throws IOException
159    {
160        return getKey(password, algorithm, keyLength, salt, false);
161    }
162
163    private static SecretKey getKey(
164        char[]  password,
165        String  algorithm,
166        int     keyLength,
167        byte[]  salt,
168        boolean des2)
169        throws IOException
170    {
171        OpenSSLPBEParametersGenerator   pGen = new OpenSSLPBEParametersGenerator();
172
173        pGen.init(PBEParametersGenerator.PKCS5PasswordToBytes(password), salt);
174
175        KeyParameter keyParam;
176        keyParam = (KeyParameter) pGen.generateDerivedParameters(keyLength * 8);
177        byte[] key = keyParam.getKey();
178        if (des2 && key.length >= 24)
179        {
180            // For DES2, we must copy first 8 bytes into the last 8 bytes.
181            System.arraycopy(key, 0, key, 16, 8);
182        }
183        return new javax.crypto.spec.SecretKeySpec(key, algorithm);
184    }
185}