us.the.mac.android.jni.helpers.EncryptedStringTest.java Source code

Java tutorial

Introduction

Here is the source code for us.the.mac.android.jni.helpers.EncryptedStringTest.java

Source

/*
 * Copyright (c) 2014 Spotify AB
 *
 * 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 us.the.mac.android.jni.helpers;

import android.support.test.InstrumentationRegistry;

import junit.framework.Assert;

import org.apache.commons.codec.binary.Base64;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

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

import static android.R.attr.key;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertNotEquals;
import static us.the.mac.android.jni.helpers.TestConstants.TEST_ENCRYPTED_RESOURCE;

import us.the.mac.android.jni.helpers.EncryptedString;
import us.the.mac.android.jni.helpers.TestConstants;

public class EncryptedStringTest {
    static {
        System.loadLibrary("test-helper-lib");
    }

    native public byte[] getNativeBytes();

    native public SecretKeySpec createSecretKeySpec();

    native public SecretKeySpec createSecretKeySpecWithParams(byte[] decodedKeyBytes, int start, int length,
            String algorithm);

    native public byte[] nativeBase64EncodeBase64(byte[] inputBytes);

    native public byte[] nativeBase64DecodeBase64(byte[] inputBytes);

    native public CryptoHelper createCryptoHelper();

    native public EncryptedString createEncryptedString();

    native public EncryptedString createEncryptedResourceString();

    native public EncryptedString createNativeEncryptedString();

    native public EncryptedString getPersistedInstance(EncryptedString object);

    native public void destroyEncryptedString(EncryptedString object);

    @Test
    public void persist() throws Exception {
        EncryptedString object = createEncryptedString();
        assertNotEquals(0, object.nPtr);
        // These properties should be set by the first native method in this case
        assertEquals(TestConstants.TEST_ENCRYPTED, object.encryptedString);

        // Now create a new empty object, but copy the nPtr field to it. Note that
        // the i field is *not* copied; that value is stored natively and should
        // be retrieved in the call to getPersistedInstance.
        EncryptedString emptyInstance = EncryptedString.testingInstance();
        emptyInstance.nPtr = object.nPtr;

        // The native test should be able to fetch the previous instance via nPtr,
        // and return to us the same instance data in a new object.
        EncryptedString result = getPersistedInstance(emptyInstance);
        assertEquals(object.nPtr, result.nPtr);
        assertEquals(object.encryptedString, result.encryptedString);

        // Always clean up after yourself, kids!
        destroyEncryptedString(object);
    }

    @Test(expected = IllegalArgumentException.class)
    native public void persistNullObject() throws Exception;

    @Test
    public void base64Decoding() throws Exception {

        byte[] startingNativeBytes = getNativeBytes();
        byte[] startingBytes = TestConstants.TEST_DECRYPT.getBytes();
        assertEquals(TestConstants.TEST_DECRYPT, new String(startingBytes));
        assertEquals(TestConstants.TEST_DECRYPT, new String(startingNativeBytes));

        byte[] encodedBytes = Base64.encodeBase64(startingBytes);
        byte[] decodedBytes = Base64.decodeBase64(encodedBytes);

        assertEquals(TestConstants.TEST_DECRYPT, new String(decodedBytes));

        byte[] nativeEncodedBytes = nativeBase64EncodeBase64(startingBytes);
        byte[] nativeDecodedBytes = nativeBase64DecodeBase64(nativeEncodedBytes);

        assertEquals(new String(encodedBytes), new String(nativeEncodedBytes));
        assertEquals(new String(decodedBytes), new String(nativeDecodedBytes));
        assertEquals(new String(startingNativeBytes), new String(nativeDecodedBytes));
        assertEquals(TestConstants.TEST_DECRYPT, new String(nativeDecodedBytes));

    }

    @Test
    public void creatingASecretKeySpec() throws Exception {

        byte[] keyBytes = TestConstants.TEST_ENCRYPTION_KEY.getBytes();
        assertEquals(TestConstants.TEST_ENCRYPTION_KEY, new String(keyBytes));

        byte[] decodedKeyBytes = Base64.decodeBase64(keyBytes);
        byte[] encodedKeyBytes = Base64.encodeBase64(decodedKeyBytes);

        //        assertEquals(TestConstants.TEST_DECODED_ENCRYPTION_KEY, new String(decodedKeyBytes));

        byte[] nativeDecodedKeyBytes = nativeBase64DecodeBase64(keyBytes);
        byte[] nativeEncodedKeyBytes = nativeBase64EncodeBase64(nativeDecodedKeyBytes);

        assertEquals(new String(encodedKeyBytes), new String(nativeEncodedKeyBytes));
        assertEquals(new String(decodedKeyBytes), new String(nativeDecodedKeyBytes));
        //        assertEquals(TestConstants.TEST_DECODED_ENCRYPTION_KEY, new String(nativeDecodedKeyBytes));

        SecretKey originalKey = new SecretKeySpec(decodedKeyBytes, 0, decodedKeyBytes.length, "AES");
        assertEquals(TestConstants.TEST_ENCRYPTION_KEY,
                new String(Base64.encodeBase64(originalKey.getEncoded())).concat("\n"));
        //        assertEquals(TestConstants.TEST_DECODED_ENCRYPTION_KEY, new String(originalKey.getEncoded()).concat("\n"));

        SecretKey nativeKey = createSecretKeySpecWithParams(decodedKeyBytes, 0, decodedKeyBytes.length, "AES");
        assertEquals(originalKey, nativeKey);

    }

    @Test
    public void javaDecryptWithSecretKey() throws Exception {

        String contents = TestConstants.TEST_ENCRYPTED_RESOURCE;
        byte[] keyBytes = TestConstants.TEST_ENCRYPTION_KEY.getBytes();
        String[] parts = contents.split(":");

        byte[] decodedKeyBytes = Base64.decodeBase64(keyBytes);
        byte[] initVector = Base64.decodeBase64(parts[0].getBytes());
        byte[] decodedValueBytes = Base64.decodeBase64(parts[1].getBytes());

        SecretKey originalKey = new SecretKeySpec(decodedKeyBytes, 0, decodedKeyBytes.length, "AES");
        Cipher cipher = Cipher.getInstance(originalKey.getAlgorithm() + "/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, originalKey, new IvParameterSpec(initVector));
        byte[] decryptedBytes = cipher.doFinal(decodedValueBytes);

        assertEquals(TestConstants.TEST_DECRYPT, new String(decryptedBytes));

    }

    @Test
    public void nativeDecryptWithSecretKey() throws Exception {

        String contents = TestConstants.TEST_ENCRYPTED_RESOURCE;
        String[] parts = contents.split(":");

        byte[] initVector = Base64.decodeBase64(parts[0].getBytes());
        byte[] decodedValueBytes = Base64.decodeBase64(parts[1].getBytes());

        SecretKey originalKey = createSecretKeySpec();
        Cipher cipher = Cipher.getInstance(originalKey.getAlgorithm() + "/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, originalKey, new IvParameterSpec(initVector));
        byte[] decryptedBytes = cipher.doFinal(decodedValueBytes);

        assertEquals(TestConstants.TEST_DECRYPT, new String(decryptedBytes));

    }

    @Test
    public void generateCrytpoHelper() throws Exception {

        CryptoHelper object = createCryptoHelper();
        assertNotEquals(0, object.nPtr);

    }

    @Test
    public void decryptString() throws Exception {
        EncryptedString object = createEncryptedString();
        assertNotEquals(0, object.nPtr);
        assertEquals(TestConstants.TEST_ENCRYPTED, object.encryptedString);

        String decryptedString = object.decrypt(EncryptedString.INLINE_STRINGS_ALGORITHM);
        assertEquals(TestConstants.TEST_DECRYPT, decryptedString);

        // Should only return the decrypted string field, the encryptedString should remain untouched
        assertEquals(TestConstants.TEST_ENCRYPTED, object.encryptedString);
    }

    @Test
    public void decryptResourceString() throws Exception {
        EncryptedString object = createEncryptedResourceString();
        assertNotEquals(0, object.nPtr);

        String encryptedString = InstrumentationRegistry.getTargetContext().getString(R.string.encryptedString);
        assertEquals(encryptedString, object.encryptedString);

        String decryptedString = object.decrypt(EncryptedString.RESOURCE_STRINGS_ALGORITHM + 1);
        assertEquals(TestConstants.TEST_DECRYPT, decryptedString);

        // Should only return the decrypted string field, the encryptedString should remain untouched
        assertEquals(encryptedString, object.encryptedString);
    }

    @Test
    public void decryptNativeEncryptedString() throws Exception {
        EncryptedString object = createNativeEncryptedString();
        assertNotEquals(0, object.nPtr);

        String encryptedString = AndroidJniApp.getEncrypted(0);
        assertEquals(encryptedString, object.encryptedString);

        String decryptedString = object.decrypt(EncryptedString.RESOURCE_STRINGS_ALGORITHM + 1);
        assertEquals(TestConstants.TEST_NATIVE_DECRYPT, decryptedString);

        // Should only return the decrypted string field, the encryptedString should remain untouched
        assertEquals(encryptedString, object.encryptedString);
    }

    @Test
    public void decryptNativeString() throws Exception {

        String decryptedString = AndroidJniApp.getS(0);
        Assert.assertEquals(TestConstants.TEST_NATIVE_DECRYPT, decryptedString);

    }

    @Test
    public void destroyEncryptedString() throws Exception {
        EncryptedString object = createEncryptedString();
        assertNotEquals(0, object.nPtr);
        assertEquals(TestConstants.TEST_ENCRYPTED, object.encryptedString);

        destroyEncryptedString(object);

        assertEquals(0, object.nPtr);
        // Destroy should only alter the nPtr field, this should remain untouched
        assertEquals(TestConstants.TEST_ENCRYPTED, object.encryptedString);
    }

    @Test
    native public void nativeIsPersistenceEnabled() throws Exception;

    @Test
    native public void isPersistenceEnabledWithoutInit() throws Exception;

    @Test
    native public void destroyInvalidClass() throws Exception;

    @Test(expected = IllegalArgumentException.class)
    native public void destroyNullObject() throws Exception;

    @Test(expected = java.lang.UnsatisfiedLinkError.class)
    public void destroyFromJava() throws Exception {
        EncryptedString object = createEncryptedString();
        assertNotEquals(0, object.nPtr);
        object.destroy();
    }
}