/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.vfs2.util;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

/**
 * Allows passwords to be encrypted and decrypted.
 * <p>
 * Warning: This uses AES128 with a fixed encryption key.
 * This is only an obfuscation no cryptographic secure protection.
 *
 * @since 2.0
 */
public class DefaultCryptor implements Cryptor
{
    private static final char[] HEX_CHARS =
            {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    private static final byte[] KEY_BYTES = {0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6F, 0x6D, 0x6D,
            0x6F, 0x6E, 0x73, 0x56, 0x46, 0x53};

    private static final int INDEX_NOT_FOUND = -1;

    private static final int BITS_IN_HALF_BYTE = 4;

    private static final char MASK = 0x0f;

    /**
     * Encrypt the plain text password.
     * <p>
     * Warning: This uses AES128 with a fixed encryption key.
     * This is only an obfuscation no cryptographic secure protection.
     *
     * @param plainKey The password.
     * @return The encrypted password String.
     * @throws Exception If an error occurs.
     */
    @Override
    public String encrypt(final String plainKey) throws Exception
    {
        final byte[] input = plainKey.getBytes();
        final SecretKeySpec key = new SecretKeySpec(KEY_BYTES, "AES");

        final Cipher cipher = Cipher.getInstance("AES");

        // encryption pass
        cipher.init(Cipher.ENCRYPT_MODE, key);

        final byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
        int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
        ctLength += cipher.doFinal(cipherText, ctLength);
        return encode(cipherText);
    }

    /**
     * Decrypts the password.
     * @param encryptedKey the encrypted password.
     * @return The plain text password.
     * @throws Exception If an error occurs.
     */
    @Override
    public String decrypt(final String encryptedKey) throws Exception
    {
        final SecretKeySpec key = new SecretKeySpec(KEY_BYTES, "AES");
        final Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, key);
        final byte[] decoded = decode(encryptedKey);
        final byte[] plainText = new byte[cipher.getOutputSize(decoded.length)];
        int ptLength = cipher.update(decoded, 0, decoded.length, plainText, 0);
        ptLength += cipher.doFinal(plainText, ptLength);
        return new String(plainText).substring(0, ptLength);
    }

    /** Hex-encode bytes. */
    private String encode(final byte[] bytes)
    {
        final StringBuilder builder = new StringBuilder();

        for (final byte b : bytes)
        {
            builder.append(HEX_CHARS[(b >> BITS_IN_HALF_BYTE) & MASK]);
            builder.append(HEX_CHARS[b & MASK]);
        }
        return builder.toString();
    }

    /** Decodes Hey-Bytes. */
    private byte[] decode(final String str)
    {
        final int length = str.length() / 2;
        final byte[] decoded = new byte[length];
        final char[] chars = str.toCharArray();
        int index = 0;
        for (int i = 0; i < chars.length; ++i)
        {
            final int id1 = indexOf(HEX_CHARS, chars[i]);
            if (id1 == -1)
            {
                throw new IllegalArgumentException("Character " + chars[i] + " at position " + i
                        + " is not a valid hexidecimal character");
            }
            final int id2 = indexOf(HEX_CHARS, chars[++i]);
            if (id2 == -1)
            {
                throw new IllegalArgumentException("Character " + chars[i] + " at position " + i
                        + " is not a valid hexidecimal character");
            }
            decoded[index++] = (byte) ((id1 << BITS_IN_HALF_BYTE) | id2);
        }
        return decoded;
    }

    private int indexOf(final char[] array, final char valueToFind)
    {
        if (array == null)
        {
            return INDEX_NOT_FOUND;
        }
        for (int i = 0; i < array.length; i++)
        {
            if (valueToFind == array[i])
            {
                return i;
            }
        }
        return INDEX_NOT_FOUND;
    }
}
