diff --git a/.gitignore b/.gitignore index 2925ed9..6327216 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ cmd/passgo/passgo cmd/passgo-gui/passgo-gui nohup.out *.apk +PgpConnect.jar diff --git a/PgpConnect.java b/PgpConnect.java new file mode 100644 index 0000000..dcd1c4c --- /dev/null +++ b/PgpConnect.java @@ -0,0 +1,286 @@ +package st.wow.git.passgo; + +import java.lang.Runnable; +import java.lang.String; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import android.os.Handler; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import org.openintents.openpgp.OpenPgpError; +import org.openintents.openpgp.OpenPgpSignatureResult; +import org.openintents.openpgp.util.OpenPgpApi; +import org.openintents.openpgp.util.OpenPgpServiceConnection; +import android.content.Context; +import android.content.ClipboardManager; +import android.content.ClipData; +import android.content.Intent; +import android.util.Log; +import android.app.Activity; +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.app.PendingIntent; +import android.content.IntentSender; +import android.content.IntentSender.OnFinished; +import android.content.IntentSender.SendIntentException; +import android.os.Bundle; + +public class PgpConnect extends Fragment { + Activity act; + Context ctx; + Handler handler; + OpenPgpServiceConnection mServiceConnection; + ClipboardManager cb; + + public PgpConnect(Activity act) { + Log.d("gio", "PgpConnect(Activity)"); + act = act; + ctx = act.getApplicationContext(); + this.handler = new Handler(ctx.getMainLooper()); + + final FragmentManager fm = act.getFragmentManager(); + final Fragment frag = this; + handler.post(new Runnable() { + public void run() { + Log.d("gio", "PgpConnect(): adding fragment"); + FragmentTransaction ft = fm.beginTransaction(); + ft.add(frag, "PgpConnect"); + ft.commitNow(); + } + }); + } + + @Override public void onAttach(Context ctx) { + super.onAttach(ctx); + Log.d("gio", "onAttach()"); + this.ctx = ctx; + this.handler = new Handler(ctx.getMainLooper()); + mServiceConnection = new OpenPgpServiceConnection(ctx, "org.sufficientlysecure.keychain"); + mServiceConnection.bindToService(); + cb = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE); + installComplete(this); + } + + + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { + Log.d("gio", "onActivityResult(" + requestCode + "): " + resultCode); + super.onActivityResult(requestCode, resultCode, data); + //activityResult(requestCode, resultCode); + if (resultCode != Activity.RESULT_OK) { + Log.d("gio", "onActivityResult: not OK"); + stringResult(requestCode, null); + return; + } + Bundle bundle = data.getExtras(); + if (bundle != null) { + for (String k : bundle.keySet()) { + Log.d("gio", "data extra:" + k); + } + } + switch (data.getAction()) { + case OpenPgpApi.ACTION_DECRYPT_VERIFY: { + Log.d("gio", "action decrypt"); + _decrypt(data, requestCode); + break; + } + case OpenPgpApi.ACTION_ENCRYPT: { + Log.d("gio", "action encrypt"); + _encrypt(data, requestCode); + break; + } + case OpenPgpApi.ACTION_GET_KEY_IDS: + Log.d("gio", "action getid"); + String[] ids = data.getStringArrayExtra("user_ids"); + + if (ids != null && ids.length > 0) { + Log.d("gio", "got some IDs"); + stringResult(requestCode, ids[0]); + } else { + Log.d("gio", "no ids"); + stringResult(requestCode, null); + } + break; + default: { + Log.d("gio", "some other action"); + } + } + } + + public void Clip(byte []dat) { + ClipData clip = ClipData.newPlainText("PgpConnect", new String(dat)); + cb.setPrimaryClip(clip); + } + + public void GetId(int chint) { + if (handler == null) { + stringResult(chint, null); + return; + } + Log.d("gio", "GetId()"); + handler.post(new Runnable() { + public void run() { + Intent data = new Intent(); + data.setAction(OpenPgpApi.ACTION_GET_KEY_IDS); + //data.setAction(OpenPgpApi.ACTION_ENCRYPT); + data.putExtra(OpenPgpApi.EXTRA_USER_IDS, new String[]{" "}); + _getid(data, chint); + } + }); + } + + public void Decrypt(byte []dat, int chint) { + if (handler == null) { + stringResult(chint, null); + return; + } + handler.post(new Runnable() { + public void run() { + Intent data = new Intent(); + data.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); + data.putExtra("DATA", dat); + _decrypt(data, chint); + } + }); + } + + private void _getid(Intent data, int chint) { + Log.d("gio","_getid"); + InputStream is = null; + ByteArrayOutputStream os = new ByteArrayOutputStream(); + OpenPgpApi api = new OpenPgpApi(this.ctx, mServiceConnection.getService()); + Intent result = api.executeApi(data, is, os); + switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { + case OpenPgpApi.RESULT_CODE_SUCCESS: { + Log.d("gio","_getid: success"); + try { + String ret = os.toString("UTF-8"); + Log.d(OpenPgpApi.TAG, "output: " + ret); + stringResult(chint, ret); + } catch (UnsupportedEncodingException e) { + Log.e("gio", "UnsupportedEncodingException", e); + stringResult(chint, null); + } + break; + } + case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: { + Log.d("gio","_getid: interaction required"); + PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); + try { + startIntentSenderForResult(pi.getIntentSender(), chint, null, 0, 0, 0, null); + } catch (IntentSender.SendIntentException e) { + Log.e("gio", "SendIntentException", e); + stringResult(chint, null); + } + break; + } + case OpenPgpApi.RESULT_CODE_ERROR: { + Log.d("gio","_getid: error"); + OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); + stringResult(chint, null); + } + } + } + private void _decrypt(Intent data, int chint) { + Log.d("gio","_decrypt"); + byte []dat = data.getByteArrayExtra("DATA"); + InputStream is = new ByteArrayInputStream(dat); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + OpenPgpApi api = new OpenPgpApi(this.ctx, mServiceConnection.getService()); + Intent result = api.executeApi(data, is, os); + switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { + case OpenPgpApi.RESULT_CODE_SUCCESS: { + try { + String ret = os.toString("UTF-8"); + Log.d(OpenPgpApi.TAG, "output: " + ret); + stringResult(chint, ret); + } catch (UnsupportedEncodingException e) { + Log.e("gio", "UnsupportedEncodingException", e); + stringResult(chint, null); + } + break; + } + case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: { + PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); + try { + startIntentSenderForResult(pi.getIntentSender(), chint, null, 0, 0, 0, null); + } catch (IntentSender.SendIntentException e) { + Log.e("gio", "SendIntentException", e); + stringResult(chint, null); + } + break; + } + case OpenPgpApi.RESULT_CODE_ERROR: { + OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); + stringResult(chint, null); + } + } + } + + public void Encrypt(byte[] id, byte[] dat, int chint) { + if (handler == null) { + stringResult(chint, null); + return; + } + handler.post(new Runnable() { + public void run() { + Intent data = new Intent(); + data.setAction(OpenPgpApi.ACTION_ENCRYPT); + data.putExtra(OpenPgpApi.EXTRA_USER_IDS, new String[]{new String(id)}); + data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); + data.putExtra("DATA", dat); + _encrypt(data, chint); + } + }); + } + + private void _encrypt(Intent data, int chint) { + Log.d("gio","_encrypt"); + byte []dat = data.getByteArrayExtra("DATA"); + InputStream is = new ByteArrayInputStream(dat); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + OpenPgpApi api = new OpenPgpApi(this.ctx, mServiceConnection.getService()); + Intent result = api.executeApi(data, is, os); + switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { + case OpenPgpApi.RESULT_CODE_SUCCESS: { + try { + String ret = os.toString("UTF-8"); + Log.d(OpenPgpApi.TAG, "output: " + ret); + stringResult(chint, ret); + } catch (UnsupportedEncodingException e) { + Log.e("gio", "UnsupportedEncodingException", e); + stringResult(chint, null); + } + + if (result.hasExtra(OpenPgpApi.RESULT_SIGNATURE)) { + OpenPgpSignatureResult sigResult + = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE); + } + break; + } + case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED: { + PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); + try { + IntentSender sender = pi.getIntentSender(); + Log.d("PgpConnect", "IntentSender:" + sender.toString()); + startIntentSenderForResult(sender, chint, null, 0, 0, 0, null); + } catch (IntentSender.SendIntentException e) { + Log.e("gio", "SendIntentException", e); + stringResult(chint, null); + } + break; + } + case OpenPgpApi.RESULT_CODE_ERROR: { + OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR); + stringResult(chint, null); + break; + } + } + } + + static private native void installComplete(PgpConnect p); + static private native void activityResult(int requestCode, int resultCode); + static private native void stringResult(int requestCode, String result); +} diff --git a/impl_android.go b/impl_android.go index e6929bb..f1d1790 100644 --- a/impl_android.go +++ b/impl_android.go @@ -1,24 +1,104 @@ //+build android +//go:generate mkdir -p classes +//go:generate javac -bootclasspath $ANDROID_HOME/platforms/android-29/android.jar -classpath openpgp-api.jar -d classes PgpConnect.java +//go:generate jar cf PgpConnect.jar -C classes . +//go:generate rm -rf classes package passgo +/* +#import +#import "jni_android.h" +*/ +import "C" + import ( "fmt" + "io/ioutil" + "path" + "log" + "strings" + "sync" + + "gioui.org/app" + _ "gioui.org/app/permission/storage" ) +var ( + h *app.Handle + waitch chan struct{} + w *app.Window + pgp PGP + InitPgpOnce sync.Once +) + +func init() { + waitch = make(chan struct{}) +} + +//export installComplete +func installComplete(env *C.JNIEnv, class C.jclass, p C.jobject) { + log.Printf("InstallComplete()") + pgp = PGP(C.NewGlobalRef(env, p)) + close(waitch) +} + +func InitPgp(x *app.Window) { + InitPgpOnce.Do(func() { + log.Printf("InitPgp()") + w = x + h = app.PlatformHandle() + SetJVM(h.JVM, h.Context) + RunInJVM(func(env *JNIEnv) { + C.InitPgpConnect(env) + }) + w.RegisterDelegate("st/wow/git/passgo/PgpConnect") + }) +} + +func stopPgp() { + waitch = make(chan struct{}) + w = nil +} + +func connect() { + <-waitch +} + //Clip copies a string to the clipboard func Clip(x string) { fmt.Println("Clipboard not implemented for this platform") } func (s *Store) nativeDecrypt(name string) (string, error) { - return "", fmt.Errorf("NOT IMPLEMENTED") + connect() + log.Printf("Decrypt(): connected") + data, err := ioutil.ReadFile(path.Join(s.Dir, strings.Join([]string{name, ".gpg"}, ""))) + if err != nil { + return "", fmt.Errorf("Error reading file: %s", err) + } + ret, err := pgp.Decrypt(string(data)) + log.Printf("Decrypt(): got %s", ret) + return ret, err } func (s *Store) nativeEncrypt(pw string) ([]byte, error) { - return nil, fmt.Errorf("NOT IMPLEMENTED") + connect() + ret, err := Encrypt("", pw) + return []byte(ret), err +} + +func Encrypt(id, data string) (string, error) { + connect() + log.Printf("Encrypt(): connected") + return pgp.Encrypt(id, data) } func nativeIdentities() ([]string, error) { - return nil, fmt.Errorf("NOT IMPLEMENTED") + log.Printf("nativeIdentities()") + connect() + log.Printf("calling pgp.GetId()") + id, err := pgp.GetId() + log.Printf("pgp.GetId() returned") + return []string{id}, err } diff --git a/jni_android.c b/jni_android.c new file mode 100644 index 0000000..ecf7ee7 --- /dev/null +++ b/jni_android.c @@ -0,0 +1,134 @@ + +#include +#include +#include +#include +#include "jni_android.h" +#include "_cgo_export.h" + +static jobject gClassLoader; +static jmethodID gFindClassMethod; + +void +SetLoader(JNIEnv* env, jobject context) { + jclass cclass = (*env)->GetObjectClass(env, context); + jmethodID gcl_id = (*env)->GetMethodID(env, cclass, "getClassLoader", "()Ljava/lang/ClassLoader;"); + jobject loader = (*env)->CallObjectMethod(env, context, gcl_id); + gClassLoader = (*env)->NewGlobalRef(env, loader); + jclass lclass = (*env)->GetObjectClass(env, loader); + gFindClassMethod = (*env)->GetMethodID(env, lclass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;"); +} + +jclass +FindClass(JNIEnv* env, char* name) { + jstring strClassName = (*env)->NewStringUTF(env, name); + return (*env)->CallObjectMethod(env, gClassLoader, gFindClassMethod, strClassName); +} + +jobject +CreateObject(JNIEnv* env, jclass cls) { + jmethodID init = (*env)->GetMethodID(env, cls, "", "()V"); + return (*env)->NewObject(env, cls, init); +} + +void +InitPgpConnect(JNIEnv* env) { + jclass cls = FindClass(env, "st/wow/git/passgo/PgpConnect"); + printf("class = %p", cls); + //jmethodID init = (*env)->GetMethodID(env, cls, "", "(Landroid/app/Activity;)V"); + //printf("init = %p", init); + //jobject ret = (*env)->NewObject(env, cls, init, act); + //printf("obj = %p", ret); + + static const JNINativeMethod actMethods[] = { + { + .name = "activityResult", + .signature = "(II)V", + .fnPtr = activityResult + }, + { + .name = "stringResult", + .signature = "(ILjava/lang/String;)V", + .fnPtr = stringResult + }, + { + .name = "installComplete", + .signature = "(Lst/wow/git/passgo/PgpConnect;)V", + .fnPtr = installComplete + }, + }; + + (*env)->RegisterNatives(env, cls, actMethods, sizeof(actMethods)/sizeof(actMethods[0])); + //return (*env)->NewGlobalRef(env, ret); +} + +void +GetId(JNIEnv* env, jobject p, int chint) { + jclass cls = (*env)->GetObjectClass(env, p); + printf("GetId(): cls = %p", cls); + jmethodID mid = (*env)->GetMethodID(env, cls, "GetId", "(I)V"); + printf("GetId(): mid = %p", mid); + (*env)->CallObjectMethod(env, p, mid, chint); +} + +void +Decrypt(JNIEnv* env, jobject p, char* cdata, int datalen, int chint) { + jbyteArray data = (*env)->NewByteArray(env, datalen); + (*env)->SetByteArrayRegion(env, data, 0, datalen, cdata); + jclass cls = (*env)->GetObjectClass(env, p); + jmethodID mid = (*env)->GetMethodID(env, cls, "Decrypt", "([BI)V"); + (*env)->CallObjectMethod(env, p, mid, data, chint); +} + +void stringResult(JNIEnv* env, jclass cls, jint requestCode, jobject response) { + if (response == 0) { + goStringResult(env, cls, requestCode, 0); + } else { + char* str = (*env)->GetStringUTFChars(env, response, NULL); + goStringResult(env, cls, requestCode, str); + } +} + +void +Encrypt(JNIEnv* env, jobject p, char* cid, int idlen, char* cdata, int datalen, int chint) { + jbyteArray id = (*env)->NewByteArray(env, idlen); + (*env)->SetByteArrayRegion(env, id, 0, idlen, cid); + jbyteArray data = (*env)->NewByteArray(env, datalen); + (*env)->SetByteArrayRegion(env, data, 0, datalen, cdata); + jclass cls = (*env)->GetObjectClass(env, p); + jmethodID mid = (*env)->GetMethodID(env, cls, "Encrypt", "([B[BI)V"); + (*env)->CallObjectMethod(env, p, mid, id, data, chint); +} + +void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID) { + (*env)->CallVoidMethod(env, obj, methodID); +} + +void CallVoidMethod1(JNIEnv *env, jobject obj, jmethodID methodID, jobject arg) { + (*env)->CallVoidMethod(env, obj, methodID, arg); +} + +jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID) { + return (*env)->CallIntMethod(env, obj, methodID); +} + +jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) { + return (*env)->GetMethodID(env, clazz, name, sig); +} + +jint GetEnv(JavaVM *vm, JNIEnv **env, jint version) { + return (*vm)->GetEnv(vm, (void **)env, version); +} + +jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args) { + return (*vm)->AttachCurrentThread(vm, p_env, thr_args); +} + +jint DetachCurrentThread(JavaVM *vm) { + return (*vm)->DetachCurrentThread(vm); +} + +jobject +NewGlobalRef(JNIEnv *env, jobject o) { + return (*env)->NewGlobalRef(env, o); +} diff --git a/jni_android.go b/jni_android.go new file mode 100644 index 0000000..44f7b14 --- /dev/null +++ b/jni_android.go @@ -0,0 +1,186 @@ +package passgo + +/* +#cgo LDFLAGS: -landroid + +#include +#include "jni_android.h" +*/ +import "C" + +import ( + "errors" + "fmt" + "log" + "runtime" + "unsafe" + "sync" +) + +var theJVM *C.JavaVM +type JNIEnv = C.JNIEnv + +func SetJVM(jvm, context uintptr) { + log.Print("set theJVM") + theJVM = (*C.JavaVM)(unsafe.Pointer(jvm)) + RunInJVM(func(env *C.JNIEnv) { + C.SetLoader(env, (C.jobject)(context)) + }) +} + +func FindClass(env *C.JNIEnv, name string) C.jclass { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + return C.FindClass((*C.JNIEnv)(env), cname) +} + +func JniCallVoidMethod(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID) { + C.CallVoidMethod(env, obj, methodID) +} + +func JniCallVoidMethod1(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID, arg uintptr) { + C.CallVoidMethod1(env, obj, methodID, C.jobject(unsafe.Pointer(arg))) +} + +func JniCallIntMethod(env *C.JNIEnv, obj C.jobject, methodID C.jmethodID) int { + return (int)(C.CallIntMethod(env, obj, methodID)) +} + +func JniGetMethodID(env *C.JNIEnv, cls C.jclass, name, sig string) C.jmethodID { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + csig := C.CString(sig) + defer C.free(unsafe.Pointer(csig)) + return C.GetMethodID(env, cls, cname, csig) +} + +func CreateObject(env *C.JNIEnv, cls C.jclass) C.jobject { + return C.CreateObject(env, (C.jclass)(cls)) +} + +type PGP C.jobject + +func InitPgpConnect(env uintptr) { + C.InitPgpConnect((*C.JNIEnv)(unsafe.Pointer(env))) +} + +//func NewPgpConnect(env uintptr, act uintptr) PGP { +// return (PGP)(C.NewPgpConnect((*C.JNIEnv)(unsafe.Pointer(env)), (C.jobject)(unsafe.Pointer(act)))) +//} + +var ( + fragChans map[int]chan string + chmux sync.Mutex + chint int +) + +func (p PGP) GetId() (string, error) { + ch := make(chan string) + chmux.Lock() + if fragChans == nil { + fragChans = make(map[int]chan string) + } + fragChans[chint] = ch + curint := chint + chint++ + chmux.Unlock() + RunInJVM(func(env *JNIEnv) { + C.GetId(env, (C.jobject)(p), C.int(curint)) + }) + log.Printf("GetId(): waiting for response") + switch x := <-ch; { + case x == "": + log.Printf("GetId(): failed") + return "", fmt.Errorf("GetId failed") + default: + log.Printf("GetId(): got %s", x) + return x, nil + } +} + +func (p PGP) Decrypt(data string) (string, error) { + ch := make(chan string) + chmux.Lock() + if fragChans == nil { + fragChans = make(map[int]chan string) + } + fragChans[chint] = ch + curint := chint + chint++ + chmux.Unlock() + + cdata := C.CString(data) + defer C.free(unsafe.Pointer(cdata)) + RunInJVM(func(env *JNIEnv) { + C.Decrypt(env, (C.jobject)(p), (*C.char)(unsafe.Pointer(cdata)), (C.int)(len(data)), C.int(curint)) + }) + switch x := <-ch; { + case x == "": + return "", fmt.Errorf("Decryption failed") + default: + return x, nil + } +} + +func (p PGP) Encrypt(id, data string) (string, error) { + ch := make(chan string) + chmux.Lock() + if fragChans == nil { + fragChans = make(map[int]chan string) + } + fragChans[chint] = ch + curint := chint + chint++ + chmux.Unlock() + + cid := C.CString(id) + defer C.free(unsafe.Pointer(cid)) + cdata := C.CString(data) + defer C.free(unsafe.Pointer(cdata)) + RunInJVM(func(env *JNIEnv) { + C.Encrypt(env, (C.jobject)(p), (*C.char)(unsafe.Pointer(cid)), (C.int)(len(id)), (*C.char)(unsafe.Pointer(cdata)), (C.int)(len(data)), C.int(curint)) + }) + switch x := <-ch; { + case x == "": + return "", fmt.Errorf("Encryption failed") + default: + return x, nil + } +} + +func RunInJVM(f func(env *C.JNIEnv)) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + var env *C.JNIEnv + var detach bool + if res := C.GetEnv(theJVM, &env, C.JNI_VERSION_1_6); res != C.JNI_OK { + if res != C.JNI_EDETACHED { + panic(fmt.Errorf("JNI GetEnv failed with error %d", res)) + } + if C.AttachCurrentThread(theJVM, &env, nil) != C.JNI_OK { + panic(errors.New("runInJVM: AttachCurrentThread failed")) + } + detach = true + } + + if detach { + defer func() { + C.DetachCurrentThread(theJVM) + }() + } + f(env) +} + +//export activityResult +func activityResult(env *C.JNIEnv, class C.jclass, request, result C.jint) { + log.Printf("activityResult (%d): %d", request, result) +} + +//export goStringResult +func goStringResult(env *C.JNIEnv, class C.jclass, request C.jint, str *C.char) { + fragChans[int(request)] <- C.GoString(str) + C.free(unsafe.Pointer(str)) + chmux.Lock() + delete(fragChans, int(request)) + chmux.Unlock() +} diff --git a/jni_android.h b/jni_android.h new file mode 100644 index 0000000..a7d68b1 --- /dev/null +++ b/jni_android.h @@ -0,0 +1,18 @@ +#include + +void SetLoader(JNIEnv* env, jobject context); +jclass FindClass(JNIEnv* env, char* name); +jobject CreateObject(JNIEnv* env, jclass cls); +void InitPgpConnect(JNIEnv* env); +void GetId(JNIEnv* env, jobject p, int chint); +void Decrypt(JNIEnv* env, jobject p, char* cdata, int datalen, int chint); +void Encrypt(JNIEnv* env, jobject p, char* cid, int idlen, char* cdata, int datalen, int chint); +void stringResult(JNIEnv* env, jclass cls, jint requestCode, jobject response); +void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID); +void CallVoidMethod1(JNIEnv *env, jobject obj, jmethodID methodID, jobject arg); +jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID); +jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig); +jint GetEnv(JavaVM *vm, JNIEnv **env, jint version); +jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args); +jint DetachCurrentThread(JavaVM *vm); +jobject NewGlobalRef(JNIEnv *env, jobject o); diff --git a/main.go b/main.go index f4531a7..673c910 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "io/ioutil" + "log" "os" "os/user" "path" @@ -134,6 +135,8 @@ func (s *Store) list(level int, p string) ([]Pass, error) { fd, err := os.Open(dir) defer fd.Close() if err != nil { + log.Printf("password store directory = %s", dir) + log.Printf("error is %s", err) return nil, fmt.Errorf("Cannot open password store") } files, err := fd.Readdir(0) @@ -262,6 +265,7 @@ func (s *Store) Decrypt(name string, prompts ...func() []byte) (string, error) { } func Identities() ([]string, error) { + log.Printf("Identities()") getKeyring() if useNative { return nativeIdentities() diff --git a/openpgp-api.jar b/openpgp-api.jar new file mode 100644 index 0000000..0ff1dc0 Binary files /dev/null and b/openpgp-api.jar differ