新增:`HttpServer`请求/应答报文进行`国密SM4`对称加密传输 【配套`SmsF`微信小程序】

This commit is contained in:
pppscn 2022-10-21 11:18:55 +08:00
parent a624ca5e8e
commit 538f440b3d
21 changed files with 621 additions and 185 deletions

View File

@ -264,6 +264,9 @@ dependencies {
//HTTP服务器https://github.com/yanzhenjie/AndServer
implementation 'cn.ppps.andserver:api:2.1.11'
kapt 'cn.ppps.andserver:processor:2.1.11'
//SM4 JAVA实现(BC实现)
api "org.bouncycastle:bcprov-jdk15on:1.69"
}
//X-Library依赖
apply from: 'x-library.gradle'

View File

@ -36,6 +36,8 @@ import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.xuexiang.xutil.XUtil
import com.xuexiang.xutil.data.ConvertTools
@Suppress("PrivatePropertyName", "PropertyName")
@Page(name = "主动控制·客户端")
@ -123,6 +125,10 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
safetyMeasuresId = R.id.rb_safety_measures_rsa
binding!!.tvSignKey.text = getString(R.string.public_key)
}
3 -> {
safetyMeasuresId = R.id.rb_safety_measures_sm4
binding!!.tvSignKey.text = getString(R.string.sm4_key)
}
else -> {
binding!!.layoutSignKey.visibility = View.GONE
}
@ -130,19 +136,23 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
binding!!.rgSafetyMeasures.check(safetyMeasuresId)
binding!!.rgSafetyMeasures.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
var safetyMeasures = 0
binding!!.layoutSignKey.visibility = View.GONE
binding!!.layoutSignKey.visibility = View.VISIBLE
when (checkedId) {
R.id.rb_safety_measures_sign -> {
safetyMeasures = 1
binding!!.tvSignKey.text = getString(R.string.sign_key)
binding!!.layoutSignKey.visibility = View.VISIBLE
}
R.id.rb_safety_measures_rsa -> {
safetyMeasures = 2
binding!!.tvSignKey.text = getString(R.string.public_key)
binding!!.layoutSignKey.visibility = View.VISIBLE
}
else -> {}
R.id.rb_safety_measures_sm4 -> {
safetyMeasures = 3
binding!!.tvSignKey.text = getString(R.string.sm4_key)
}
else -> {
binding!!.layoutSignKey.visibility = View.GONE
}
}
HttpServerUtils.clientSafetyMeasures = safetyMeasures
}
@ -195,6 +205,10 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
safetyMeasuresId = R.id.rb_safety_measures_rsa
binding!!.tvSignKey.text = getString(R.string.public_key)
}
"3" -> {
safetyMeasuresId = R.id.rb_safety_measures_sm4
binding!!.tvSignKey.text = getString(R.string.sm4_key)
}
else -> {
binding!!.tvSignKey.visibility = View.GONE
binding!!.etSignKey.visibility = View.GONE
@ -254,8 +268,8 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
msgMap["timestamp"] = timestamp
val clientSignKey = HttpServerUtils.clientSignKey.toString()
if ((HttpServerUtils.clientSafetyMeasures == 1 || HttpServerUtils.clientSafetyMeasures == 2) && TextUtils.isEmpty(clientSignKey)) {
if (needToast) XToastUtils.error("请输入签名密钥或RSA公")
if (HttpServerUtils.clientSafetyMeasures != 0 && TextUtils.isEmpty(clientSignKey)) {
if (needToast) XToastUtils.error("请输入签名密钥/RSA公钥/SM4密")
return
}
@ -273,20 +287,37 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE).timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
if (needToast) XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
when (HttpServerUtils.clientSafetyMeasures) {
2 -> {
try {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
if (needToast) XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
3 -> {
try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
//requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
if (needToast) XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
else -> {
postRequest.upJson(requestMsg)
}
postRequest.upString(requestMsg)
} else {
postRequest.upJson(requestMsg)
}
if (needToast) mCountDownHelper?.start()
@ -304,6 +335,11 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC)
}
val resp: BaseResponse<ConfigData> = Gson().fromJson(json, object : TypeToken<BaseResponse<ConfigData>>() {}.type)
if (resp.code == 200) {

View File

@ -27,6 +27,7 @@ import com.xuexiang.xui.widget.button.SmoothCheckBox
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.xuexiang.xui.widget.picker.XSeekBar
import com.xuexiang.xutil.app.ServiceUtils
import com.xuexiang.xutil.data.ConvertTools
import com.xuexiang.xutil.net.NetworkUtils
import com.xuexiang.xutil.system.ClipboardUtils
import java.io.File
@ -92,6 +93,10 @@ class ServerFragment : BaseFragment<FragmentServerBinding?>(), View.OnClickListe
binding!!.layoutPrivateKey.visibility = View.VISIBLE
binding!!.layoutPublicKey.visibility = View.VISIBLE
}
3 -> {
safetyMeasuresId = R.id.rb_safety_measures_sm4
binding!!.layoutSm4Key.visibility = View.VISIBLE
}
else -> {}
}
binding!!.rgSafetyMeasures.check(safetyMeasuresId)
@ -101,6 +106,7 @@ class ServerFragment : BaseFragment<FragmentServerBinding?>(), View.OnClickListe
binding!!.layoutTimeTolerance.visibility = View.GONE
binding!!.layoutPrivateKey.visibility = View.GONE
binding!!.layoutPublicKey.visibility = View.GONE
binding!!.layoutSm4Key.visibility = View.GONE
when (checkedId) {
R.id.rb_safety_measures_sign -> {
safetyMeasures = 1
@ -112,11 +118,26 @@ class ServerFragment : BaseFragment<FragmentServerBinding?>(), View.OnClickListe
binding!!.layoutPrivateKey.visibility = View.VISIBLE
binding!!.layoutPublicKey.visibility = View.VISIBLE
}
R.id.rb_safety_measures_sm4 -> {
safetyMeasures = 3
binding!!.layoutSm4Key.visibility = View.VISIBLE
}
else -> {}
}
HttpServerUtils.safetyMeasures = safetyMeasures
}
//SM4密钥
binding!!.btnSm4Key.setOnClickListener(this)
binding!!.etSm4Key.setText(HttpServerUtils.serverSm4Key)
binding!!.etSm4Key.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {
HttpServerUtils.serverSm4Key = binding!!.etSm4Key.text.toString().trim()
}
})
//RSA公私钥
binding!!.btnCopyPublicKey.setOnClickListener(this)
binding!!.btnGenerateKey.setOnClickListener(this)
@ -221,6 +242,13 @@ class ServerFragment : BaseFragment<FragmentServerBinding?>(), View.OnClickListe
}
refreshButtonText()
}
R.id.btn_sm4_key -> {
val key = ConvertTools.bytes2HexString(SM4Crypt.createSM4Key())
println("SM4密钥$key")
ClipboardUtils.copyText(key)
binding!!.etSm4Key.setText(key)
XToastUtils.info(getString(R.string.sign_key_tips))
}
R.id.btn_generate_key -> {
val generator = KeyPairGenerator.getInstance("RSA") //密钥生成器
generator.initialize(2048)

View File

@ -20,6 +20,7 @@ import com.xuexiang.xrouter.utils.TextUtils
import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.grouplist.XUIGroupListView
import com.xuexiang.xutil.data.ConvertTools
@Suppress("PropertyName")
@Page(name = "远程查电量")
@ -67,20 +68,37 @@ class BatteryQueryFragment : BaseFragment<FragmentClientBatteryQueryBinding?>()
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
when (HttpServerUtils.clientSafetyMeasures) {
2 -> {
try {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
3 -> {
try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
//requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
else -> {
postRequest.upJson(requestMsg)
}
postRequest.upString(requestMsg)
} else {
postRequest.upJson(requestMsg)
}
postRequest.execute(object : SimpleCallBack<String>() {
@ -96,6 +114,11 @@ class BatteryQueryFragment : BaseFragment<FragmentClientBatteryQueryBinding?>()
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC)
}
val resp: BaseResponse<BatteryInfo> = Gson().fromJson(json, object : TypeToken<BaseResponse<BatteryInfo>>() {}.type)
if (resp.code == 200) {

View File

@ -35,6 +35,7 @@ import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xui.utils.SnackbarUtils
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.searchview.MaterialSearchView
import com.xuexiang.xutil.data.ConvertTools
import com.xuexiang.xutil.data.DateUtils
import com.xuexiang.xutil.system.ClipboardUtils
import me.samlss.broccoli.Broccoli
@ -216,20 +217,37 @@ class CallQueryFragment : BaseFragment<FragmentClientCallQueryBinding?>() {
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
when (HttpServerUtils.clientSafetyMeasures) {
2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
3 -> {
try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
//requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
else -> {
postRequest.upJson(requestMsg)
}
postRequest.upString(requestMsg)
} else {
postRequest.upJson(requestMsg)
}
postRequest.execute(object : SimpleCallBack<String>() {
@ -245,6 +263,11 @@ class CallQueryFragment : BaseFragment<FragmentClientCallQueryBinding?>() {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC)
}
val resp: BaseResponse<List<CallInfo>?> = Gson().fromJson(json, object : TypeToken<BaseResponse<List<CallInfo>?>>() {}.type)
if (resp.code == 200) {

View File

@ -31,6 +31,7 @@ import com.xuexiang.xui.utils.CountDownButtonHelper
import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xutil.app.AppUtils
import com.xuexiang.xutil.data.ConvertTools
import com.xuexiang.xutil.file.FileIOUtils
import com.xuexiang.xutil.file.FileUtils
import java.io.File
@ -255,20 +256,37 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
when (HttpServerUtils.clientSafetyMeasures) {
2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
3 -> {
try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
//requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
else -> {
postRequest.upJson(requestMsg)
}
postRequest.upString(requestMsg)
} else {
postRequest.upJson(requestMsg)
}
postRequest.execute(object : SimpleCallBack<String>() {
@ -285,6 +303,11 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC)
}
val resp: BaseResponse<String> = Gson().fromJson(json, object : TypeToken<BaseResponse<String>>() {}.type)
if (resp.code == 200) {
@ -336,20 +359,37 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
when (HttpServerUtils.clientSafetyMeasures) {
2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
3 -> {
try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
//requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
else -> {
postRequest.upJson(requestMsg)
}
postRequest.upString(requestMsg)
} else {
postRequest.upJson(requestMsg)
}
postRequest.execute(object : SimpleCallBack<String>() {
@ -366,6 +406,11 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC)
}
//替换Date字段为当前时间

View File

@ -36,6 +36,7 @@ import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xui.utils.SnackbarUtils
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.searchview.MaterialSearchView
import com.xuexiang.xutil.data.ConvertTools
import com.xuexiang.xutil.system.ClipboardUtils
import me.samlss.broccoli.Broccoli
@ -199,20 +200,37 @@ class ContactQueryFragment : BaseFragment<FragmentClientContactQueryBinding?>()
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
when (HttpServerUtils.clientSafetyMeasures) {
2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
3 -> {
try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
//requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
else -> {
postRequest.upJson(requestMsg)
}
postRequest.upString(requestMsg)
} else {
postRequest.upJson(requestMsg)
}
postRequest.execute(object : SimpleCallBack<String>() {
@ -228,6 +246,11 @@ class ContactQueryFragment : BaseFragment<FragmentClientContactQueryBinding?>()
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC)
}
val resp: BaseResponse<List<ContactInfo>?> = Gson().fromJson(json, object : TypeToken<BaseResponse<List<ContactInfo>?>>() {}.type)
if (resp.code == 200) {

View File

@ -37,6 +37,7 @@ import com.xuexiang.xui.utils.SnackbarUtils
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.searchview.MaterialSearchView
import com.xuexiang.xui.widget.searchview.MaterialSearchView.SearchViewListener
import com.xuexiang.xutil.data.ConvertTools
import com.xuexiang.xutil.data.DateUtils
import me.samlss.broccoli.Broccoli
@ -206,20 +207,37 @@ class SmsQueryFragment : BaseFragment<FragmentClientSmsQueryBinding?>() {
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
when (HttpServerUtils.clientSafetyMeasures) {
2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
3 -> {
try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
//requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
else -> {
postRequest.upJson(requestMsg)
}
postRequest.upString(requestMsg)
} else {
postRequest.upJson(requestMsg)
}
postRequest.execute(object : SimpleCallBack<String>() {
@ -235,6 +253,11 @@ class SmsQueryFragment : BaseFragment<FragmentClientSmsQueryBinding?>() {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC)
}
val resp: BaseResponse<List<SmsInfo>?> = Gson().fromJson(json, object : TypeToken<BaseResponse<List<SmsInfo>?>>() {}.type)
if (resp.code == 200) {

View File

@ -23,6 +23,7 @@ import com.xuexiang.xrouter.utils.TextUtils
import com.xuexiang.xui.utils.CountDownButtonHelper
import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xutil.data.ConvertTools
@Suppress("PropertyName")
@Page(name = "远程发短信")
@ -121,20 +122,37 @@ class SmsSendFragment : BaseFragment<FragmentClientSmsSendBinding?>(), View.OnCl
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
when (HttpServerUtils.clientSafetyMeasures) {
2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
3 -> {
try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
//requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
else -> {
postRequest.upJson(requestMsg)
}
postRequest.upString(requestMsg)
} else {
postRequest.upJson(requestMsg)
}
mCountDownHelper?.start()
@ -152,6 +170,11 @@ class SmsSendFragment : BaseFragment<FragmentClientSmsSendBinding?>(), View.OnCl
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC)
}
val resp: BaseResponse<String> = Gson().fromJson(json, object : TypeToken<BaseResponse<String>>() {}.type)
if (resp.code == 200) {

View File

@ -23,6 +23,7 @@ import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.xuexiang.xutil.data.ConvertTools
@Suppress("PropertyName")
@Page(name = "远程WOL")
@ -151,20 +152,37 @@ class WolSendFragment : BaseFragment<FragmentClientWolSendBinding?>(), View.OnCl
.cacheMode(CacheMode.NO_CACHE)
.timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
when (HttpServerUtils.clientSafetyMeasures) {
2 -> {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
try {
requestMsg = Base64.encode(requestMsg.toByteArray())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
3 -> {
try {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
//requestMsg = Base64.encode(requestMsg.toByteArray())
val encryptCBC = SM4Crypt.encrypt(requestMsg.toByteArray(), sm4Key)
requestMsg = ConvertTools.bytes2HexString(encryptCBC)
Log.i(TAG, "requestMsg: $requestMsg")
} catch (e: Exception) {
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
e.printStackTrace()
return
}
postRequest.upString(requestMsg)
}
else -> {
postRequest.upJson(requestMsg)
}
postRequest.upString(requestMsg)
} else {
postRequest.upJson(requestMsg)
}
mCountDownHelper?.start()
@ -182,6 +200,11 @@ class WolSendFragment : BaseFragment<FragmentClientWolSendBinding?>(), View.OnCl
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json))
} else if (HttpServerUtils.clientSafetyMeasures == 3) {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
json = String(decryptCBC)
}
val resp: BaseResponse<String> = Gson().fromJson(json, object : TypeToken<BaseResponse<String>>() {}.type)
if (resp.code == 200) {

View File

@ -4,6 +4,8 @@ import android.util.Log
import com.idormy.sms.forwarder.utils.Base64
import com.idormy.sms.forwarder.utils.HttpServerUtils
import com.idormy.sms.forwarder.utils.RSACrypt
import com.idormy.sms.forwarder.utils.SM4Crypt
import com.xuexiang.xutil.data.ConvertTools
import com.yanzhenjie.andserver.annotation.Resolver
import com.yanzhenjie.andserver.error.HttpException
import com.yanzhenjie.andserver.framework.ExceptionResolver
@ -13,6 +15,7 @@ import com.yanzhenjie.andserver.http.HttpRequest
import com.yanzhenjie.andserver.http.HttpResponse
import com.yanzhenjie.andserver.http.StatusCode
@Suppress("PrivatePropertyName")
@Resolver
class AppExceptionResolver : ExceptionResolver {
@ -31,13 +34,22 @@ class AppExceptionResolver : ExceptionResolver {
//返回统一结构报文
var resp = HttpServerUtils.response(e.message.toString())
Log.d(TAG, "resp: $resp")
if (HttpServerUtils.safetyMeasures != 2) {
response.setBody(JsonBody(resp))
} else {
val privateKey = RSACrypt.getPrivateKey(HttpServerUtils.serverPrivateKey.toString())
resp = Base64.encode(resp.toByteArray())
resp = RSACrypt.encryptByPrivateKey(resp, privateKey)
response.setBody(StringBody(resp))
when (HttpServerUtils.safetyMeasures) {
2 -> {
val privateKey = RSACrypt.getPrivateKey(HttpServerUtils.serverPrivateKey.toString())
resp = Base64.encode(resp.toByteArray())
resp = RSACrypt.encryptByPrivateKey(resp, privateKey)
response.setBody(StringBody(resp))
}
3 -> {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.serverSm4Key.toString())
//response = Base64.encode(response.toByteArray())
val encryptCBC = SM4Crypt.encrypt(resp.toByteArray(), sm4Key)
response.setBody(StringBody(ConvertTools.bytes2HexString(encryptCBC)))
}
else -> {
response.setBody(JsonBody(resp))
}
}
}

View File

@ -6,7 +6,9 @@ import com.idormy.sms.forwarder.server.model.BaseRequest
import com.idormy.sms.forwarder.utils.Base64
import com.idormy.sms.forwarder.utils.HttpServerUtils
import com.idormy.sms.forwarder.utils.RSACrypt
import com.idormy.sms.forwarder.utils.SM4Crypt
import com.xuexiang.xrouter.utils.TextUtils
import com.xuexiang.xutil.data.ConvertTools
import com.yanzhenjie.andserver.annotation.Converter
import com.yanzhenjie.andserver.error.HttpException
import com.yanzhenjie.andserver.framework.MessageConverter
@ -32,14 +34,21 @@ class AppMessageConverter : MessageConverter {
var response = HttpServerUtils.response(output)
Log.d(TAG, "response: $response")
if (HttpServerUtils.safetyMeasures != 2) {
return JsonBody(response)
return when (HttpServerUtils.safetyMeasures) {
2 -> {
val privateKey = RSACrypt.getPrivateKey(HttpServerUtils.serverPrivateKey.toString())
response = Base64.encode(response.toByteArray())
response = RSACrypt.encryptByPrivateKey(response, privateKey)
StringBody(response)
}
3 -> {
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.serverSm4Key.toString())
//response = Base64.encode(response.toByteArray())
val encryptCBC = SM4Crypt.encrypt(response.toByteArray(), sm4Key)
StringBody(ConvertTools.bytes2HexString(encryptCBC))
}
else -> JsonBody(response)
}
val privateKey = RSACrypt.getPrivateKey(HttpServerUtils.serverPrivateKey.toString())
response = Base64.encode(response.toByteArray())
response = RSACrypt.encryptByPrivateKey(response, privateKey)
return StringBody(response)
}
@Throws(IOException::class)
@ -60,6 +69,18 @@ class AppMessageConverter : MessageConverter {
json = RSACrypt.decryptByPrivateKey(json, privateKey)
json = String(Base64.decode(json))
Log.d(TAG, "Json: $json")
} else if (HttpServerUtils.safetyMeasures == 3) {
if (TextUtils.isEmpty(HttpServerUtils.serverSm4Key)) {
Log.e(TAG, "SM4解密失败: SM4密钥为空")
throw HttpException(500, "服务端未配置SM4密钥")
}
val sm4Key = ConvertTools.hexStringToByteArray(HttpServerUtils.clientSignKey.toString())
val encryptCBC = ConvertTools.hexStringToByteArray(json)
val decryptCBC = SM4Crypt.decrypt(encryptCBC, sm4Key)
//json = String(Base64.decode(decryptCBC.toString()))
json = String(decryptCBC)
Log.d(TAG, "Json: $json")
}
//修改接口数据中的null、“”为默认值

View File

@ -9,6 +9,7 @@ import com.yanzhenjie.andserver.http.HttpRequest
import com.yanzhenjie.andserver.http.HttpResponse
//@Interceptor
@Suppress("unused")
class LoginInterceptor : HandlerInterceptor {
override fun onIntercept(
request: HttpRequest,

View File

@ -325,6 +325,7 @@ const val SP_ENABLE_SERVER_AUTORUN = "enable_server_autorun"
const val SP_SERVER_SAFETY_MEASURES = "server_safety_measures"
const val SP_SERVER_SIGN_KEY = "server_sign_key"
const val SP_SERVER_TIME_TOLERANCE = "server_time_tolerance"
const val SP_SERVER_SM4_KEY = "server_sm4_key"
const val SP_SERVER_PUBLIC_KEY = "server_public_key"
const val SP_SERVER_PRIVATE_KEY = "server_private_key"
const val SP_SERVER_WEB_PATH = "server_web_path"
@ -341,6 +342,7 @@ const val SP_SERVER_HISTORY = "server_history"
const val SP_SERVER_CONFIG = "server_config"
const val SP_CLIENT_SAFETY_MEASURES = "client_safety_measures"
const val SP_CLIENT_SIGN_KEY = "client_sign_key"
var CLIENT_FRAGMENT_LIST = listOf(
PageInfo(
getString(R.string.api_clone),

View File

@ -40,6 +40,14 @@ class HttpServerUtils private constructor() {
MMKVUtils.put(SP_SERVER_SAFETY_MEASURES, safetyMeasures)
}
//服务端SM4密钥
@JvmStatic
var serverSm4Key: String?
get() = MMKVUtils.getString(SP_SERVER_SM4_KEY, "")
set(serverSm4Key) {
MMKVUtils.put(SP_SERVER_SM4_KEY, serverSm4Key)
}
//服务端RSA公钥
@JvmStatic
var serverPublicKey: String?

View File

@ -0,0 +1,62 @@
package com.idormy.sms.forwarder.utils
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
/**
* SM4分组密码算法是我国自主设计的分组对称密码算法
*/
@Suppress("unused", "MemberVisibilityCanBePrivate")
object SM4Crypt {
const val SM4_CBC_NOPADDING = "SM4/CBC/NoPadding"
const val SM4_CBC_PKCS5 = "SM4/CBC/PKCS5Padding"
const val SM4_CBC_PKCS7 = "SM4/CBC/PKCS7Padding"
const val SM4_ECB_NOPADDING = "SM4/ECB/NoPadding"
const val SM4_ECB_PKCS5 = "SM4/ECB/PKCS5Padding"
const val SM4_ECB_PKCS7 = "SM4/ECB/PKCS7Padding"
private val BC_PROVIDER = BouncyCastleProvider()
private val SM4_CBC_IV = byteArrayOf(3, 5, 6, 9, 6, 9, 5, 9, 3, 5, 6, 9, 6, 9, 5, 9)
/**
* 获取随机密钥
*/
fun createSM4Key(): ByteArray {
val seed = ByteArray(16)
val random = SecureRandom()
random.nextBytes(seed)
return seed
}
@JvmOverloads
fun encrypt(source: ByteArray, key: ByteArray, mode: String = SM4_CBC_PKCS7, iv: ByteArray? = SM4_CBC_IV): ByteArray {
return doSM4(true, source, key, mode, iv)
}
@JvmOverloads
fun decrypt(source: ByteArray, key: ByteArray, mode: String = SM4_CBC_PKCS7, iv: ByteArray? = SM4_CBC_IV): ByteArray {
return doSM4(false, source, key, mode, iv)
}
private fun doSM4(forEncryption: Boolean, source: ByteArray, key: ByteArray, mode: String, iv: ByteArray?): ByteArray {
return try {
val cryptMode = if (forEncryption) 1 else 2
val sm4Key = SecretKeySpec(key, "SM4")
val cipher = Cipher.getInstance(mode, BC_PROVIDER)
if (iv == null) {
cipher.init(cryptMode, sm4Key)
} else {
val ivParameterSpec = IvParameterSpec(iv)
cipher.init(cryptMode, sm4Key, ivParameterSpec)
}
cipher.doFinal(source)
} catch (var9: Exception) {
var9.printStackTrace()
ByteArray(0)
}
}
}

View File

@ -67,42 +67,57 @@
style="@style/settingBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="vertical"
android:paddingEnd="10dp"
tools:ignore="RtlSymmetry">
<TextView
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/safety_measures"
android:textStyle="bold" />
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/safety_measures"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="@string/safety_measures_tips"
android:textSize="10sp"
tools:ignore="SmallSp" />
</LinearLayout>
<RadioGroup
android:id="@+id/rg_safety_measures"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="3dp"
style="@style/rg_style"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_safety_measures_none"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/rg_rb_style"
android:checked="true"
android:text="@string/safety_measures_none"
android:textSize="11sp" />
android:text="@string/safety_measures_none" />
<RadioButton
android:id="@+id/rb_safety_measures_sign"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/safety_measures_sign"
android:textSize="11sp" />
style="@style/rg_rb_style"
android:text="@string/safety_measures_sign" />
<RadioButton
android:id="@+id/rb_safety_measures_rsa"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/safety_measures_encrypt"
android:textSize="11sp" />
style="@style/rg_rb_style"
android:text="@string/safety_measures_rsa" />
<RadioButton
android:id="@+id/rb_safety_measures_sm4"
style="@style/rg_rb_style"
android:text="@string/safety_measures_sm4" />
</RadioGroup>

View File

@ -137,42 +137,57 @@
style="@style/settingBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="vertical"
android:paddingEnd="10dp"
tools:ignore="RtlSymmetry">
<TextView
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/safety_measures"
android:textStyle="bold" />
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/safety_measures"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="@string/safety_measures_tips"
android:textSize="10sp"
tools:ignore="SmallSp" />
</LinearLayout>
<RadioGroup
android:id="@+id/rg_safety_measures"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="3dp"
style="@style/rg_style"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_safety_measures_none"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/rg_rb_style"
android:checked="true"
android:text="@string/safety_measures_none"
android:textSize="11sp" />
android:text="@string/safety_measures_none" />
<RadioButton
android:id="@+id/rb_safety_measures_sign"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/safety_measures_sign"
android:textSize="11sp" />
style="@style/rg_rb_style"
android:text="@string/safety_measures_sign" />
<RadioButton
android:id="@+id/rb_safety_measures_rsa"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/safety_measures_encrypt"
android:textSize="11sp" />
style="@style/rg_rb_style"
android:text="@string/safety_measures_rsa" />
<RadioButton
android:id="@+id/rb_safety_measures_sm4"
style="@style/rg_rb_style"
android:text="@string/safety_measures_sm4" />
</RadioGroup>
@ -365,6 +380,47 @@
</LinearLayout>
<LinearLayout
android:id="@+id/layout_sm4_key"
style="@style/settingBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingEnd="15dp"
android:visibility="gone"
tools:ignore="RtlSymmetry">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sm4_key"
android:textStyle="bold" />
<com.xuexiang.xui.widget.edittext.ClearEditText
android:id="@+id/et_sm4_key"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_weight="1"
android:hint="@string/sm4_key_tips" />
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
android:id="@+id/btn_sm4_key"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:gravity="center"
android:padding="5dp"
android:text="@string/generate_key"
android:textColor="@color/white"
android:textSize="10sp"
app:sb_color_unpressed="@color/colorPrimary"
app:sb_ripple_color="@color/white"
app:sb_ripple_duration="500"
app:sb_shape_type="rectangle"
tools:ignore="SmallSp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -608,7 +664,8 @@
<LinearLayout
style="@style/settingBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
tools:ignore="TooManyViews">
<LinearLayout
android:layout_width="0dp"

View File

@ -876,7 +876,7 @@
<string name="sms_keyword_hint">Input keywords to fuzzy match SMS content</string>
<string name="contact_keyword_hint">Pure numbers match numbers / non-numbers match names</string>
<string name="call_keyword_hint">Input keyword to fuzzy match mobile phone number</string>
<string name="server_settings_tips2">Fill two items according to the config of server, the signature key is optional</string>
<string name="server_settings_tips2">Fill these items according to the config of server</string>
<string name="service_address">Server Url</string>
<string name="service_address_hint">E.g: http://127.0.0.1:5000</string>
<string name="features_list">Features List</string>
@ -925,9 +925,11 @@
<string name="auto_clean_logs_tips">0=disabled, scan when battery change</string>
<string name="day">Day</string>
<string name="safety_measures">Safety Measures</string>
<string name="safety_measures_tips">The client and server must be the same. It is strongly recommended to enable encryption when accessing the public network.</string>
<string name="safety_measures_none">None</string>
<string name="safety_measures_sign">Sign</string>
<string name="safety_measures_encrypt">Encrypt</string>
<string name="safety_measures_rsa">RSA Encrypt</string>
<string name="safety_measures_sm4">SM4 Encrypt</string>
<string name="web_path_tips">See Github Wiki, download to Download directory</string>
<string name="time_tolerance">Time Tolerance</string>
<string name="time_tolerance_tips">Minimize time tolerance to avoid request replay attacks</string>
@ -937,4 +939,6 @@
<string name="public_key">Public Key</string>
<string name="public_key_tips">Public key is used on the client: client request message public key encryption, server private key decryption</string>
<string name="copy_public_key">Copy</string>
<string name="sm4_key">SM4 Key</string>
<string name="sm4_key_tips">Client or server interaction messages are all encrypted and decrypted using SM4</string>
</resources>

View File

@ -877,7 +877,7 @@
<string name="sms_keyword_hint">输入关键字模糊匹配短信内容</string>
<string name="contact_keyword_hint">纯数字匹配号码/非数字匹配姓名</string>
<string name="call_keyword_hint">输入关键字模糊匹配手机号码</string>
<string name="server_settings_tips2">按照主动控制·服务端的配置填写以下两项,签名密钥可选</string>
<string name="server_settings_tips2">按照主动控制·服务端的配置填写以下项目</string>
<string name="service_address">服务地址</string>
<string name="service_address_hint">例如http://127.0.0.1:5000</string>
<string name="features_list">功能列表</string>
@ -926,9 +926,11 @@
<string name="auto_clean_logs_tips">0=禁用,触发机制:每次电量变化时扫描</string>
<string name="day"></string>
<string name="safety_measures">安全措施</string>
<string name="safety_measures_tips">客户端与服务端必须一致,强烈建议公网访问时启用加密</string>
<string name="safety_measures_none">不需要</string>
<string name="safety_measures_sign">校验签名</string>
<string name="safety_measures_encrypt">加密传输</string>
<string name="safety_measures_rsa">RSA加密</string>
<string name="safety_measures_sm4">SM4加密</string>
<string name="web_path_tips">参见 Github Wiki下载到 Download 目录</string>
<string name="time_tolerance">客户端与服务端时间容差</string>
<string name="time_tolerance_tips">尽量缩短时间容差,避免请求重放攻击</string>
@ -938,4 +940,6 @@
<string name="public_key">RSA公钥</string>
<string name="public_key_tips">RSA公钥用在客户端客户端请求报文公钥加密服务端私钥解密</string>
<string name="copy_public_key">复制公钥</string>
<string name="sm4_key">SM4密钥</string>
<string name="sm4_key_tips">客户端/服务端交互采用SM4加解密</string>
</resources>

View File

@ -179,7 +179,7 @@
<item name="android:singleLine">true</item>
<item name="android:padding">0dp</item>
<item name="android:layout_margin">0dp</item>
<item name="android:textSize">13sp</item>
<item name="android:textSize">12sp</item>
</style>
<style name="rg_rb_style_wrap">
@ -188,14 +188,14 @@
<item name="android:singleLine">true</item>
<item name="android:padding">0dp</item>
<item name="android:layout_marginEnd">5dp</item>
<item name="android:textSize">13sp</item>
<item name="android:textSize">12sp</item>
</style>
<style name="rg_rb_style_match">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:singleLine">true</item>
<item name="android:textSize">13sp</item>
<item name="android:textSize">12sp</item>
</style>
</resources>