android 的 Facebook 隐藏加密始终不可用

Facebook Conceal crypto for android is always unavailable

我无法在我的 android 应用程序中使用 Facebook Conceal 库。 cryptocrypto.isAvailable() 上似乎总是 return 正确。 此外,我使用的 Android 1.0.2 没有明确列出所包含的库,但我已将其放在正确的 libs 文件夹中。

我包含了上一个 link 中可用的 Jar 和本机二进制文件。 .zip 文件包含在构建中:

compile fileTree(dir: 'libs', include: ['*.jar', '*.zip'])

构建似乎有效。我验证了本机库:cryptox.soconceal.so 包含在 apk/libs 中,而其他包含 com.facebook.crypto 等包的 jar 二进制文件包含在 classes.dex 中。

以下是activity代码:

import com.facebook.crypto.Crypto;
import com.facebook.crypto.Entity;
import com.facebook.crypto.keychain.SharedPrefsBackedKeyChain;
import com.facebook.crypto.util.SystemNativeCryptoLibrary;

public class ConcealActivity extends Activity implements View.OnClickListener {
public static String filename = "data.txt";
public static String filepath = "concealedata";
public static String TAG = "com.zing.ConcealActivity";
File myInternalFile;
Crypto crypto;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_conceal);

    Log.i(TAG, "created method.");
    ContextWrapper contextWrapper = new ContextWrapper(getApplicationContext());
    File directory = contextWrapper.getDir(filepath, Context.MODE_PRIVATE);
    myInternalFile = new File(directory, filename);
    crypto = new Crypto(new SharedPrefsBackedKeyChain(this), new SystemNativeCryptoLibrary());
    Button cencrypt = (Button) findViewById(R.id.cencrypt);
    cencrypt.setOnClickListener(this);

    Button cdecrypt = (Button) findViewById(R.id.cdecrypt);
    cdecrypt.setOnClickListener(this);
}

@Override
public void onClick(View v) {
    Log.i(TAG, "onclick method.");
    EditText myInputText = (EditText) findViewById(R.id.inputText);
    TextView responseText = (TextView) findViewById(R.id.responseText);
    String myData = "";

    switch (v.getId()) {
        case R.id.cencrypt:
            encryptandsave(myInputText.getText().toString().getBytes());
            myInputText.setText("");
            responseText.setText(readFile(myInternalFile));
            break;

        case R.id.cdecrypt:
            responseText.setText(readanddecrypt());
            break;
    }
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_conceal, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

// 下面的第一个条件总是满足意味着库没有正确加载。

// Encrypts the data and saves to directory
public void encryptandsave(byte[] plainTextBytes) {
    try {
    // Check for whether the crypto functionality is available
    // This might fail if android does not load libaries correctly.
        if (!crypto.isAvailable()) {
            Log.e(TAG, "Cipher unavailable.");
            return;
        }

        OutputStream fileStream = new BufferedOutputStream(new FileOutputStream(myInternalFile));
        OutputStream outputStream = crypto.getCipherOutputStream(fileStream, new Entity("Password"));
        outputStream.write(plainTextBytes);
        outputStream.close();
    } catch (Exception e) {
        Log.e(TAG, "EXCEPTION encryptandsave: " + e.getMessage());
    }
}

// decode encrypted file and returns Bitmap
private String readanddecrypt() {
    try {
        if (!crypto.isAvailable()) {
            Log.e(TAG, "Cipher unavailable.");
            return "";
        }
        FileInputStream fileStream = new FileInputStream(filename);
        InputStream inputStream = crypto.getCipherInputStream(fileStream, new Entity("Password"));
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        int read;
        byte[] buffer = new byte[1024];
        while ((read = inputStream.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
        inputStream.close();
        return out.toString();
    } catch (Exception e) {
        Log.e(TAG, "EXCEPTION readanddecrypt: " + e.getMessage());
    }
    return null;
}

public String readFile(File internalFile) {
    StringBuilder sb = new StringBuilder();
    try {
        FileInputStream fis = new FileInputStream(internalFile);
        DataInputStream in = new DataInputStream(fis);
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String strLine;
        while ((strLine = br.readLine()) != null) {
            sb.append(strLine);
        }
        in.close();
    } catch (IOException e) {
        Log.e(TAG, "EXCEPTION readFile: " + e.getMessage());
        return "";
    }
    return sb.toString();
}

}

我不确定库或代码是否有问题。

在 jar 中,代码似乎在

中失败
com.facebook.crypto.util.SystemNativeCryptoLibrary.java

private static final ArrayList<String> LIBS = new ArrayList<String>() {{
  add("cryptox");
  add("conceal");
}};

// 在执行下面这一段时抛出 java.lang.UnsatisfiedLinkError 异常:

for (String name : LIBS) {
  System.loadLibrary(name);

Assaf's solution 是有效的。
下面是库需要进入的结构。
项目:
|--库:
|--|--armeabi:
|--|--|--.so 文件。

请注意,下载的 libs.zip 中的所有库文件都压缩在 libs 根文件夹中,需要将其更改为 lib 以便将库正确捆绑在 .apk

你可以尝试将.so文件相应地放到/app/src/main/jniLibs/下。

app
+-src
  +-main
    +-jniLibs
      +-armeabi
      | +-libconceal.so
      +-armeabi-v7a
      | +-libconceal.so
      +-mips
      +-x86
        +-libconceal.so