Code Monkey home page Code Monkey logo

Comments (6)

siyengar avatar siyengar commented on August 24, 2024

Entity does not actually wrap the key. Entity is meant to be a publicly visible filename to prevent against substitution attacks.

The key comes from the KeyChain you supply while initializing the Crypto object. The default SharedPreferencesKeyChain generates a key per device. You can make the KeyChain return the same key on both devices by creating a custom KeyChain. The key needs to be NativeGCMCipher.KEY_LENGTH length. You can look at the SharedPreferencesKeyChain as a sample https://github.com/facebook/conceal/blob/master/java/com/facebook/crypto/keychain/SharedPrefsBackedKeyChain.java

from conceal.

siyengar avatar siyengar commented on August 24, 2024

I hope that answers your question. I'm closing out the task. Feel free to reopen if you have follow up questions.

from conceal.

eliaszkubala avatar eliaszkubala commented on August 24, 2024

Hi Siyengar, thanks for your answer.

I have two question. I made a class like you sad. CustomSharedPrefsBackedKeyChain.java

Here is a code: http://ideone.com/3Zlgos.
I added fixed String key 2cda8e8ebb37f2b1. I worry it doesn't safe so,
I thought about create own constructor with random key variable, But I can't initialize Crypto more than once so I can't pass my own key when i wan't decrypt or encrypt data.

crypto = new Crypto(
new CustomSharedPrefsBackedKeyChain(c, "new random key"),
new SystemNativeCryptoLibrary());

So, my question is,

  1. Is making a KeyChain which return the same key on booth devices and only protect file by random entity is safe?
  2. There is any solution for initialize Cyrpto more than once.

from conceal.

siyengar avatar siyengar commented on August 24, 2024

You can initialize Crypto as many times as you want, just call new Crypto()

For the 2 device problem, you'll need a way to share a key between the 2 devices. It sounds like you want an encrypted communication protocol between devices and not a pure file encryption solution. You might want to consider using a secure communication protocol instead like SSL. This completely depends on the communication medium and the nature of your app.

from conceal.

eliaszkubala avatar eliaszkubala commented on August 24, 2024

Okey,

I made this class CustomSharedPrefsBackedKeyChain and it's work.

package XXX;
import com.facebook.crypto.exception.KeyChainException;
import com.facebook.crypto.keychain.KeyChain;
import com.facebook.crypto.keychain.SecureRandomFix;
import java.security.SecureRandom;
import java.util.Arrays;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Base64;
import android.util.Log;

import com.facebook.crypto.cipher.NativeGCMCipher;
import com.facebook.crypto.mac.NativeMac;

/**
 * Created by TheKing on 2014-12-29.
 */
public class CustomSharedPrefsBackedKeyChain implements KeyChain {
    // Visible for testing.
    /* package */ static final String SHARED_PREF_NAME = "crypto";
    /* package */ static final String CIPHER_KEY_PREF = "cipher_key";
    /* package */ static final String MAC_KEY_PREF = "mac_key";

    private final SharedPreferences mSharedPreferences;
    private final SecureRandom mSecureRandom;
    private String key = null;

    protected byte[] mCipherKey;
    protected boolean mSetCipherKey;

    protected byte[] mMacKey;
    protected boolean mSetMacKey;

    private static final SecureRandomFix sSecureRandomFix = new SecureRandomFix();
    private String log = "KeyChain";

    public CustomSharedPrefsBackedKeyChain(Context context, String key) {
        Log.d(log, "CustomSharedPrefsBackedKeyChain");
        mSharedPreferences = context.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
        mSecureRandom = new SecureRandom();
        this.key = key;
    }

    @Override
    public synchronized byte[] getCipherKey() throws KeyChainException {
        if (!mSetCipherKey) {
            mCipherKey = maybeGenerateKey(CIPHER_KEY_PREF, NativeGCMCipher.KEY_LENGTH);
        }
        mSetCipherKey = true;
        return mCipherKey;
    }

    @Override
    public byte[] getMacKey() throws KeyChainException {
        if (!mSetMacKey) {
            mMacKey = maybeGenerateKey(MAC_KEY_PREF, NativeMac.KEY_LENGTH);
        }
        mSetMacKey = true;
        return mMacKey;
    }

    @Override
    public byte[] getNewIV() throws KeyChainException {
        sSecureRandomFix.tryApplyFixes();
        byte[] iv = new byte[NativeGCMCipher.IV_LENGTH];
        mSecureRandom.nextBytes(iv);
        return iv;
    }

    @Override
    public synchronized void destroyKeys() {
        mSetCipherKey = false;
        mSetMacKey = false;
        Arrays.fill(mCipherKey, (byte) 0);
        Arrays.fill(mMacKey, (byte) 0);
        mCipherKey = null;
        mMacKey = null;
        SharedPreferences.Editor editor = mSharedPreferences.edit();
        editor.remove(CIPHER_KEY_PREF);
        editor.remove(MAC_KEY_PREF);
        //editor.commit();
    }

    /**
     * Generates a key associated with a preference.
     */
    private byte[] maybeGenerateKey(String pref, int length) throws KeyChainException {
        String base64Key = mSharedPreferences.getString(pref, null);

        String key;
        if(length == NativeGCMCipher.KEY_LENGTH)
            key = this.key;
        else if(length == NativeMac.KEY_LENGTH)
            key = (this.key + this.key + this.key +this.key);
        else
            key = this.key;

        base64Key = key.toString();

        if (base64Key == null) {
            // Generate key if it doesn't exist.
            return generateAndSaveKey(pref, length);
        } else {
            return base64Key.getBytes();
        }
    }

    private byte[] generateAndSaveKey(String pref, int length) throws KeyChainException {
        sSecureRandomFix.tryApplyFixes();
        byte[] key = new byte[length];
        if(length == NativeGCMCipher.KEY_LENGTH)
            key = this.key.getBytes();
        else if(length == NativeMac.KEY_LENGTH)
            key = (this.key + this.key + this.key +this.key).getBytes();
        else
            key = this.key.getBytes();

        mSecureRandom.nextBytes(key);
        // Store the session key.
        SharedPreferences.Editor editor = mSharedPreferences.edit();
        editor.putString(
                pref,
                encodeForPrefs(key));
        //editor.commit();

        Log.d(log, key.toString());

        return key;
    }

    /**
     * Visible for testing.
     */
  byte[] decodeFromPrefs(String keyString) {
        if (keyString == null) {
            return null;
        }
        Log.d(log, keyString.toString());
        return Base64.decode(keyString, Base64.DEFAULT);
    }

    /**
     * Visible for testing.
    */
    String encodeForPrefs(byte[] key) {
        if (key == null ) {
                return null;
        }
        return Base64.encodeToString(key, Base64.DEFAULT);
    }

}

To initialize use this

Crypto crypto = new Crypto(new CustomSharedPrefsBackedKeyChain(c, key), new SystemNativeCryptoLibrary());

Thanks very much for your time.

from conceal.

huttarl avatar huttarl commented on August 24, 2024

@eliaszkubala thank you for sharing this implementation! I had a very similar need.

from conceal.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.