我正在尝试为Android中的服务器和客户端应用实施SRP protocol。我检查过OpenSSL是否支持SRP协议但是如何从Android应用程序访问OpenSSL API? JNI是访问OpenSSL C API的唯一方法吗?是否有任何样本我可以参考如何构建Android的OpenSSL并通过JNI调用OpenSSL SRP API。
答案 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_cb
和ssl_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并获取名称:
因此,您将用于SSL_CTX_set_cipher_list
或SSL_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";