如何从Android应用程序调用OpenSSL SRP API?

时间:2016-08-08 14:37:56

标签: android android-ndk openssl java-native-interface single-responsibility-principle

我正在尝试为Android中的服务器和客户端应用实施SRP protocol。我检查过OpenSSL是否支持SRP协议但是如何从Android应用程序访问OpenSSL API? JNI是访问OpenSSL C API的唯一方法吗?是否有任何样本我可以参考如何构建Android的OpenSSL并通过JNI调用OpenSSL SRP API。

1 个答案:

答案 0 :(得分:2)

  

我正在尝试实施SRP protocol

我也喜欢SRP。请务必使用Thomas Wu的规范,或IETF规范的第6版。

  

OpenSSL支持SRP协议,但如何从Android应用程序访问OpenSSL API? JNI是访问OpenSSL C API的唯一方法吗?

您也可以选择Bouncy Castle来实现Java。

  

是否有任何样本我可以参考如何构建适用于Android的OpenSSL ...

请参阅OpenSSL wiki上的OpenSSL and Android

Android携带OpenSSL的副本,但我不确定它是否包含SRP。

  

是否有任何我可以参考的样本...通过JNI调用OpenSSL SRP API。

不是我知道的。您最接近的是s_client的源代码,-srpuser <user>等选项,srp_arg_st等数据结构以及ssl_srp_verify_param_cbssl_give_srp_client_pwd_cb等函数。< / p>

您可以在s_client找到<openssl src dir>/apps/s_client.c的源代码。 1365行看起来很有趣(从1.0.2h开始):

# ifndef OPENSSL_NO_SRP
    if (srp_arg.srplogin) {
        if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg.srplogin)) {
            BIO_printf(bio_err, "Unable to set SRP username\n");
            goto end;
        }
        srp_arg.msg = c_msg;
        srp_arg.debug = c_debug;
        SSL_CTX_set_srp_cb_arg(ctx, &srp_arg);
        SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb);
        SSL_CTX_set_srp_strength(ctx, srp_arg.strength);
        if (c_msg || c_debug || srp_arg.amp == 0)
            SSL_CTX_set_srp_verify_param_callback(ctx,
                                                  ssl_srp_verify_param_cb);
    }
# endif

来自第475行的srp_arg_st

/* This is a context that we pass to all callbacks */
typedef struct srp_arg_st {
    char *srppassin;
    char *srplogin;
    int msg;                    /* copy from c_msg */
    int debug;                  /* copy from c_debug */
    int amp;                    /* allow more groups */
    int strength /* minimal size for N */ ;
} SRP_ARG;

显然,OpenSSL是本机C,不使用JNI。

  

如何调用OpenSSL SRP API ......?

在最高级别,您需要在C中执行两到三项操作。将它们视为OpenSSL wiki中标准TLS Client的补充。 (我正在踩着Android / JNI部分)。

首先,您需要设置SSL_CTX_set_srp_*_callback。回调是库如何提示您的TLS客户端提供用户名和密码等信息。

第二个,删除所有非SRP密码套件。这意味着您使用 "HIGH:!aNULL:!MD5:!RC4" 等密码列表。

第三个​​,您只使用SRP密码套件。我不确定使用"HIGH:!aNULL:..."时密码列表的外观如何。但您可以手动选择密码列表:

$ openssl ciphers -v | grep SRP | grep -v DSS | cut -f 1 -d ' '
SRP-RSA-AES-256-CBC-SHA
SRP-AES-256-CBC-SHA
SRP-RSA-AES-128-CBC-SHA
SRP-AES-128-CBC-SHA
SRP-RSA-3DES-EDE-CBC-SHA
SRP-3DES-EDE-CBC-SHA

如果您转到openssl ciphers man page,那么您应该能够使用密码列表中所需的名称交叉引用SRP-RSA-AES-256-CBC-SHA。不幸的是,SRP密码套件丢失了。

但是,您可以访问ICANN的TLS paramter registry并获取名称:

  • SRP-RSA-AES-256-CBC-SHA→TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA
  • SRP-AES-256-CBC-SHA→TLS_SRP_SHA_WITH_AES_256_CBC_SHA
  • SRP-RSA-AES-128-CBC-SHA→TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA
  • SRP-AES-128-CBC-SHA→TLS_SRP_SHA_WITH_AES_128_CBC_SHA
  • SRP-RSA-3DES-EDE-CBC-SHA→TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA
  • SRP-3DES-EDE-CBC-SHA→TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA

因此,您将用于SSL_CTX_set_cipher_listSSL_set_cipher_list的字符串:

static const char const PREFERRED_CIPHERS[] =
   "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
    TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
    TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA";