新增:`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 //HTTP服务器https://github.com/yanzhenjie/AndServer
implementation 'cn.ppps.andserver:api:2.1.11' implementation 'cn.ppps.andserver:api:2.1.11'
kapt 'cn.ppps.andserver:processor:2.1.11' kapt 'cn.ppps.andserver:processor:2.1.11'
//SM4 JAVA实现(BC实现)
api "org.bouncycastle:bcprov-jdk15on:1.69"
} }
//X-Library依赖 //X-Library依赖
apply from: 'x-library.gradle' 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.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.xuexiang.xutil.XUtil import com.xuexiang.xutil.XUtil
import com.xuexiang.xutil.data.ConvertTools
@Suppress("PrivatePropertyName", "PropertyName") @Suppress("PrivatePropertyName", "PropertyName")
@Page(name = "主动控制·客户端") @Page(name = "主动控制·客户端")
@ -123,6 +125,10 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
safetyMeasuresId = R.id.rb_safety_measures_rsa safetyMeasuresId = R.id.rb_safety_measures_rsa
binding!!.tvSignKey.text = getString(R.string.public_key) 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 -> { else -> {
binding!!.layoutSignKey.visibility = View.GONE binding!!.layoutSignKey.visibility = View.GONE
} }
@ -130,19 +136,23 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
binding!!.rgSafetyMeasures.check(safetyMeasuresId) binding!!.rgSafetyMeasures.check(safetyMeasuresId)
binding!!.rgSafetyMeasures.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int -> binding!!.rgSafetyMeasures.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
var safetyMeasures = 0 var safetyMeasures = 0
binding!!.layoutSignKey.visibility = View.GONE binding!!.layoutSignKey.visibility = View.VISIBLE
when (checkedId) { when (checkedId) {
R.id.rb_safety_measures_sign -> { R.id.rb_safety_measures_sign -> {
safetyMeasures = 1 safetyMeasures = 1
binding!!.tvSignKey.text = getString(R.string.sign_key) binding!!.tvSignKey.text = getString(R.string.sign_key)
binding!!.layoutSignKey.visibility = View.VISIBLE
} }
R.id.rb_safety_measures_rsa -> { R.id.rb_safety_measures_rsa -> {
safetyMeasures = 2 safetyMeasures = 2
binding!!.tvSignKey.text = getString(R.string.public_key) 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 HttpServerUtils.clientSafetyMeasures = safetyMeasures
} }
@ -195,6 +205,10 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
safetyMeasuresId = R.id.rb_safety_measures_rsa safetyMeasuresId = R.id.rb_safety_measures_rsa
binding!!.tvSignKey.text = getString(R.string.public_key) 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 -> { else -> {
binding!!.tvSignKey.visibility = View.GONE binding!!.tvSignKey.visibility = View.GONE
binding!!.etSignKey.visibility = View.GONE binding!!.etSignKey.visibility = View.GONE
@ -254,8 +268,8 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
msgMap["timestamp"] = timestamp msgMap["timestamp"] = timestamp
val clientSignKey = HttpServerUtils.clientSignKey.toString() val clientSignKey = HttpServerUtils.clientSignKey.toString()
if ((HttpServerUtils.clientSafetyMeasures == 1 || HttpServerUtils.clientSafetyMeasures == 2) && TextUtils.isEmpty(clientSignKey)) { if (HttpServerUtils.clientSafetyMeasures != 0 && TextUtils.isEmpty(clientSignKey)) {
if (needToast) XToastUtils.error("请输入签名密钥或RSA公") if (needToast) XToastUtils.error("请输入签名密钥/RSA公钥/SM4密")
return return
} }
@ -273,20 +287,37 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s .timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
.cacheMode(CacheMode.NO_CACHE).timeStamp(true) .cacheMode(CacheMode.NO_CACHE).timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) { when (HttpServerUtils.clientSafetyMeasures) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) 2 -> {
try { try {
requestMsg = Base64.encode(requestMsg.toByteArray()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = Base64.encode(requestMsg.toByteArray())
Log.i(TAG, "requestMsg: $requestMsg") requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
} catch (e: Exception) { Log.i(TAG, "requestMsg: $requestMsg")
if (needToast) XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message) } catch (e: Exception) {
e.printStackTrace() if (needToast) XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
return 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() if (needToast) mCountDownHelper?.start()
@ -304,6 +335,11 @@ class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListe
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) 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) val resp: BaseResponse<ConfigData> = Gson().fromJson(json, object : TypeToken<BaseResponse<ConfigData>>() {}.type)
if (resp.code == 200) { 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.dialog.materialdialog.MaterialDialog
import com.xuexiang.xui.widget.picker.XSeekBar import com.xuexiang.xui.widget.picker.XSeekBar
import com.xuexiang.xutil.app.ServiceUtils import com.xuexiang.xutil.app.ServiceUtils
import com.xuexiang.xutil.data.ConvertTools
import com.xuexiang.xutil.net.NetworkUtils import com.xuexiang.xutil.net.NetworkUtils
import com.xuexiang.xutil.system.ClipboardUtils import com.xuexiang.xutil.system.ClipboardUtils
import java.io.File import java.io.File
@ -92,6 +93,10 @@ class ServerFragment : BaseFragment<FragmentServerBinding?>(), View.OnClickListe
binding!!.layoutPrivateKey.visibility = View.VISIBLE binding!!.layoutPrivateKey.visibility = View.VISIBLE
binding!!.layoutPublicKey.visibility = View.VISIBLE binding!!.layoutPublicKey.visibility = View.VISIBLE
} }
3 -> {
safetyMeasuresId = R.id.rb_safety_measures_sm4
binding!!.layoutSm4Key.visibility = View.VISIBLE
}
else -> {} else -> {}
} }
binding!!.rgSafetyMeasures.check(safetyMeasuresId) binding!!.rgSafetyMeasures.check(safetyMeasuresId)
@ -101,6 +106,7 @@ class ServerFragment : BaseFragment<FragmentServerBinding?>(), View.OnClickListe
binding!!.layoutTimeTolerance.visibility = View.GONE binding!!.layoutTimeTolerance.visibility = View.GONE
binding!!.layoutPrivateKey.visibility = View.GONE binding!!.layoutPrivateKey.visibility = View.GONE
binding!!.layoutPublicKey.visibility = View.GONE binding!!.layoutPublicKey.visibility = View.GONE
binding!!.layoutSm4Key.visibility = View.GONE
when (checkedId) { when (checkedId) {
R.id.rb_safety_measures_sign -> { R.id.rb_safety_measures_sign -> {
safetyMeasures = 1 safetyMeasures = 1
@ -112,11 +118,26 @@ class ServerFragment : BaseFragment<FragmentServerBinding?>(), View.OnClickListe
binding!!.layoutPrivateKey.visibility = View.VISIBLE binding!!.layoutPrivateKey.visibility = View.VISIBLE
binding!!.layoutPublicKey.visibility = View.VISIBLE binding!!.layoutPublicKey.visibility = View.VISIBLE
} }
R.id.rb_safety_measures_sm4 -> {
safetyMeasures = 3
binding!!.layoutSm4Key.visibility = View.VISIBLE
}
else -> {} else -> {}
} }
HttpServerUtils.safetyMeasures = safetyMeasures 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公私钥 //RSA公私钥
binding!!.btnCopyPublicKey.setOnClickListener(this) binding!!.btnCopyPublicKey.setOnClickListener(this)
binding!!.btnGenerateKey.setOnClickListener(this) binding!!.btnGenerateKey.setOnClickListener(this)
@ -221,6 +242,13 @@ class ServerFragment : BaseFragment<FragmentServerBinding?>(), View.OnClickListe
} }
refreshButtonText() 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 -> { R.id.btn_generate_key -> {
val generator = KeyPairGenerator.getInstance("RSA") //密钥生成器 val generator = KeyPairGenerator.getInstance("RSA") //密钥生成器
generator.initialize(2048) 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.utils.ResUtils
import com.xuexiang.xui.widget.actionbar.TitleBar import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.grouplist.XUIGroupListView import com.xuexiang.xui.widget.grouplist.XUIGroupListView
import com.xuexiang.xutil.data.ConvertTools
@Suppress("PropertyName") @Suppress("PropertyName")
@Page(name = "远程查电量") @Page(name = "远程查电量")
@ -67,20 +68,37 @@ class BatteryQueryFragment : BaseFragment<FragmentClientBatteryQueryBinding?>()
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE)
.timeStamp(true) .timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) { when (HttpServerUtils.clientSafetyMeasures) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) 2 -> {
try { try {
requestMsg = Base64.encode(requestMsg.toByteArray()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = Base64.encode(requestMsg.toByteArray())
Log.i(TAG, "requestMsg: $requestMsg") requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
} catch (e: Exception) { Log.i(TAG, "requestMsg: $requestMsg")
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message) } catch (e: Exception) {
e.printStackTrace() XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
return 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>() { postRequest.execute(object : SimpleCallBack<String>() {
@ -96,6 +114,11 @@ class BatteryQueryFragment : BaseFragment<FragmentClientBatteryQueryBinding?>()
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) 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) val resp: BaseResponse<BatteryInfo> = Gson().fromJson(json, object : TypeToken<BaseResponse<BatteryInfo>>() {}.type)
if (resp.code == 200) { 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.utils.SnackbarUtils
import com.xuexiang.xui.widget.actionbar.TitleBar import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.searchview.MaterialSearchView import com.xuexiang.xui.widget.searchview.MaterialSearchView
import com.xuexiang.xutil.data.ConvertTools
import com.xuexiang.xutil.data.DateUtils import com.xuexiang.xutil.data.DateUtils
import com.xuexiang.xutil.system.ClipboardUtils import com.xuexiang.xutil.system.ClipboardUtils
import me.samlss.broccoli.Broccoli import me.samlss.broccoli.Broccoli
@ -216,20 +217,37 @@ class CallQueryFragment : BaseFragment<FragmentClientCallQueryBinding?>() {
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE)
.timeStamp(true) .timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) { when (HttpServerUtils.clientSafetyMeasures) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) 2 -> {
try { val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
requestMsg = Base64.encode(requestMsg.toByteArray()) try {
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = Base64.encode(requestMsg.toByteArray())
Log.i(TAG, "requestMsg: $requestMsg") requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
} catch (e: Exception) { Log.i(TAG, "requestMsg: $requestMsg")
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message) } catch (e: Exception) {
e.printStackTrace() XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
return 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>() { postRequest.execute(object : SimpleCallBack<String>() {
@ -245,6 +263,11 @@ class CallQueryFragment : BaseFragment<FragmentClientCallQueryBinding?>() {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) 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) val resp: BaseResponse<List<CallInfo>?> = Gson().fromJson(json, object : TypeToken<BaseResponse<List<CallInfo>?>>() {}.type)
if (resp.code == 200) { 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.utils.ResUtils
import com.xuexiang.xui.widget.actionbar.TitleBar import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xutil.app.AppUtils import com.xuexiang.xutil.app.AppUtils
import com.xuexiang.xutil.data.ConvertTools
import com.xuexiang.xutil.file.FileIOUtils import com.xuexiang.xutil.file.FileIOUtils
import com.xuexiang.xutil.file.FileUtils import com.xuexiang.xutil.file.FileUtils
import java.io.File import java.io.File
@ -255,20 +256,37 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE)
.timeStamp(true) .timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) { when (HttpServerUtils.clientSafetyMeasures) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) 2 -> {
try { val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
requestMsg = Base64.encode(requestMsg.toByteArray()) try {
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = Base64.encode(requestMsg.toByteArray())
Log.i(TAG, "requestMsg: $requestMsg") requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
} catch (e: Exception) { Log.i(TAG, "requestMsg: $requestMsg")
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message) } catch (e: Exception) {
e.printStackTrace() XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
return 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>() { postRequest.execute(object : SimpleCallBack<String>() {
@ -285,6 +303,11 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) 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) val resp: BaseResponse<String> = Gson().fromJson(json, object : TypeToken<BaseResponse<String>>() {}.type)
if (resp.code == 200) { if (resp.code == 200) {
@ -336,20 +359,37 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE)
.timeStamp(true) .timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) { when (HttpServerUtils.clientSafetyMeasures) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) 2 -> {
try { val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
requestMsg = Base64.encode(requestMsg.toByteArray()) try {
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = Base64.encode(requestMsg.toByteArray())
Log.i(TAG, "requestMsg: $requestMsg") requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
} catch (e: Exception) { Log.i(TAG, "requestMsg: $requestMsg")
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message) } catch (e: Exception) {
e.printStackTrace() XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
return 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>() { postRequest.execute(object : SimpleCallBack<String>() {
@ -366,6 +406,11 @@ class CloneFragment : BaseFragment<FragmentClientCloneBinding?>(), View.OnClickL
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) 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字段为当前时间 //替换Date字段为当前时间

View File

@ -36,6 +36,7 @@ import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xui.utils.SnackbarUtils import com.xuexiang.xui.utils.SnackbarUtils
import com.xuexiang.xui.widget.actionbar.TitleBar import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.searchview.MaterialSearchView import com.xuexiang.xui.widget.searchview.MaterialSearchView
import com.xuexiang.xutil.data.ConvertTools
import com.xuexiang.xutil.system.ClipboardUtils import com.xuexiang.xutil.system.ClipboardUtils
import me.samlss.broccoli.Broccoli import me.samlss.broccoli.Broccoli
@ -199,20 +200,37 @@ class ContactQueryFragment : BaseFragment<FragmentClientContactQueryBinding?>()
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE)
.timeStamp(true) .timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) { when (HttpServerUtils.clientSafetyMeasures) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) 2 -> {
try { val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
requestMsg = Base64.encode(requestMsg.toByteArray()) try {
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = Base64.encode(requestMsg.toByteArray())
Log.i(TAG, "requestMsg: $requestMsg") requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
} catch (e: Exception) { Log.i(TAG, "requestMsg: $requestMsg")
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message) } catch (e: Exception) {
e.printStackTrace() XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
return 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>() { postRequest.execute(object : SimpleCallBack<String>() {
@ -228,6 +246,11 @@ class ContactQueryFragment : BaseFragment<FragmentClientContactQueryBinding?>()
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) 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) val resp: BaseResponse<List<ContactInfo>?> = Gson().fromJson(json, object : TypeToken<BaseResponse<List<ContactInfo>?>>() {}.type)
if (resp.code == 200) { 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.actionbar.TitleBar
import com.xuexiang.xui.widget.searchview.MaterialSearchView import com.xuexiang.xui.widget.searchview.MaterialSearchView
import com.xuexiang.xui.widget.searchview.MaterialSearchView.SearchViewListener import com.xuexiang.xui.widget.searchview.MaterialSearchView.SearchViewListener
import com.xuexiang.xutil.data.ConvertTools
import com.xuexiang.xutil.data.DateUtils import com.xuexiang.xutil.data.DateUtils
import me.samlss.broccoli.Broccoli import me.samlss.broccoli.Broccoli
@ -206,20 +207,37 @@ class SmsQueryFragment : BaseFragment<FragmentClientSmsQueryBinding?>() {
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE)
.timeStamp(true) .timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) { when (HttpServerUtils.clientSafetyMeasures) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) 2 -> {
try { val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
requestMsg = Base64.encode(requestMsg.toByteArray()) try {
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = Base64.encode(requestMsg.toByteArray())
Log.i(TAG, "requestMsg: $requestMsg") requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
} catch (e: Exception) { Log.i(TAG, "requestMsg: $requestMsg")
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message) } catch (e: Exception) {
e.printStackTrace() XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
return 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>() { postRequest.execute(object : SimpleCallBack<String>() {
@ -235,6 +253,11 @@ class SmsQueryFragment : BaseFragment<FragmentClientSmsQueryBinding?>() {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) 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) val resp: BaseResponse<List<SmsInfo>?> = Gson().fromJson(json, object : TypeToken<BaseResponse<List<SmsInfo>?>>() {}.type)
if (resp.code == 200) { 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.CountDownButtonHelper
import com.xuexiang.xui.utils.ResUtils import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xui.widget.actionbar.TitleBar import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xutil.data.ConvertTools
@Suppress("PropertyName") @Suppress("PropertyName")
@Page(name = "远程发短信") @Page(name = "远程发短信")
@ -121,20 +122,37 @@ class SmsSendFragment : BaseFragment<FragmentClientSmsSendBinding?>(), View.OnCl
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE)
.timeStamp(true) .timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) { when (HttpServerUtils.clientSafetyMeasures) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) 2 -> {
try { val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
requestMsg = Base64.encode(requestMsg.toByteArray()) try {
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = Base64.encode(requestMsg.toByteArray())
Log.i(TAG, "requestMsg: $requestMsg") requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
} catch (e: Exception) { Log.i(TAG, "requestMsg: $requestMsg")
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message) } catch (e: Exception) {
e.printStackTrace() XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
return 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() mCountDownHelper?.start()
@ -152,6 +170,11 @@ class SmsSendFragment : BaseFragment<FragmentClientSmsSendBinding?>(), View.OnCl
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) 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) val resp: BaseResponse<String> = Gson().fromJson(json, object : TypeToken<BaseResponse<String>>() {}.type)
if (resp.code == 200) { 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.actionbar.TitleBar
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.xuexiang.xutil.data.ConvertTools
@Suppress("PropertyName") @Suppress("PropertyName")
@Page(name = "远程WOL") @Page(name = "远程WOL")
@ -151,20 +152,37 @@ class WolSendFragment : BaseFragment<FragmentClientWolSendBinding?>(), View.OnCl
.cacheMode(CacheMode.NO_CACHE) .cacheMode(CacheMode.NO_CACHE)
.timeStamp(true) .timeStamp(true)
if (HttpServerUtils.clientSafetyMeasures == 2) { when (HttpServerUtils.clientSafetyMeasures) {
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) 2 -> {
try { val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
requestMsg = Base64.encode(requestMsg.toByteArray()) try {
requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey) requestMsg = Base64.encode(requestMsg.toByteArray())
Log.i(TAG, "requestMsg: $requestMsg") requestMsg = RSACrypt.encryptByPublicKey(requestMsg, publicKey)
} catch (e: Exception) { Log.i(TAG, "requestMsg: $requestMsg")
XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message) } catch (e: Exception) {
e.printStackTrace() XToastUtils.error(ResUtils.getString(R.string.request_failed) + e.message)
return 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() mCountDownHelper?.start()
@ -182,6 +200,11 @@ class WolSendFragment : BaseFragment<FragmentClientWolSendBinding?>(), View.OnCl
val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString()) val publicKey = RSACrypt.getPublicKey(HttpServerUtils.clientSignKey.toString())
json = RSACrypt.decryptByPublicKey(json, publicKey) json = RSACrypt.decryptByPublicKey(json, publicKey)
json = String(Base64.decode(json)) 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) val resp: BaseResponse<String> = Gson().fromJson(json, object : TypeToken<BaseResponse<String>>() {}.type)
if (resp.code == 200) { 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.Base64
import com.idormy.sms.forwarder.utils.HttpServerUtils import com.idormy.sms.forwarder.utils.HttpServerUtils
import com.idormy.sms.forwarder.utils.RSACrypt 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.annotation.Resolver
import com.yanzhenjie.andserver.error.HttpException import com.yanzhenjie.andserver.error.HttpException
import com.yanzhenjie.andserver.framework.ExceptionResolver 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.HttpResponse
import com.yanzhenjie.andserver.http.StatusCode import com.yanzhenjie.andserver.http.StatusCode
@Suppress("PrivatePropertyName")
@Resolver @Resolver
class AppExceptionResolver : ExceptionResolver { class AppExceptionResolver : ExceptionResolver {
@ -31,13 +34,22 @@ class AppExceptionResolver : ExceptionResolver {
//返回统一结构报文 //返回统一结构报文
var resp = HttpServerUtils.response(e.message.toString()) var resp = HttpServerUtils.response(e.message.toString())
Log.d(TAG, "resp: $resp") Log.d(TAG, "resp: $resp")
if (HttpServerUtils.safetyMeasures != 2) { when (HttpServerUtils.safetyMeasures) {
response.setBody(JsonBody(resp)) 2 -> {
} else { val privateKey = RSACrypt.getPrivateKey(HttpServerUtils.serverPrivateKey.toString())
val privateKey = RSACrypt.getPrivateKey(HttpServerUtils.serverPrivateKey.toString()) resp = Base64.encode(resp.toByteArray())
resp = Base64.encode(resp.toByteArray()) resp = RSACrypt.encryptByPrivateKey(resp, privateKey)
resp = RSACrypt.encryptByPrivateKey(resp, privateKey) response.setBody(StringBody(resp))
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.Base64
import com.idormy.sms.forwarder.utils.HttpServerUtils import com.idormy.sms.forwarder.utils.HttpServerUtils
import com.idormy.sms.forwarder.utils.RSACrypt import com.idormy.sms.forwarder.utils.RSACrypt
import com.idormy.sms.forwarder.utils.SM4Crypt
import com.xuexiang.xrouter.utils.TextUtils import com.xuexiang.xrouter.utils.TextUtils
import com.xuexiang.xutil.data.ConvertTools
import com.yanzhenjie.andserver.annotation.Converter import com.yanzhenjie.andserver.annotation.Converter
import com.yanzhenjie.andserver.error.HttpException import com.yanzhenjie.andserver.error.HttpException
import com.yanzhenjie.andserver.framework.MessageConverter import com.yanzhenjie.andserver.framework.MessageConverter
@ -32,14 +34,21 @@ class AppMessageConverter : MessageConverter {
var response = HttpServerUtils.response(output) var response = HttpServerUtils.response(output)
Log.d(TAG, "response: $response") Log.d(TAG, "response: $response")
if (HttpServerUtils.safetyMeasures != 2) { return when (HttpServerUtils.safetyMeasures) {
return JsonBody(response) 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) @Throws(IOException::class)
@ -60,6 +69,18 @@ class AppMessageConverter : MessageConverter {
json = RSACrypt.decryptByPrivateKey(json, privateKey) json = RSACrypt.decryptByPrivateKey(json, privateKey)
json = String(Base64.decode(json)) json = String(Base64.decode(json))
Log.d(TAG, "Json: $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、“”为默认值 //修改接口数据中的null、“”为默认值

View File

@ -9,6 +9,7 @@ import com.yanzhenjie.andserver.http.HttpRequest
import com.yanzhenjie.andserver.http.HttpResponse import com.yanzhenjie.andserver.http.HttpResponse
//@Interceptor //@Interceptor
@Suppress("unused")
class LoginInterceptor : HandlerInterceptor { class LoginInterceptor : HandlerInterceptor {
override fun onIntercept( override fun onIntercept(
request: HttpRequest, 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_SAFETY_MEASURES = "server_safety_measures"
const val SP_SERVER_SIGN_KEY = "server_sign_key" const val SP_SERVER_SIGN_KEY = "server_sign_key"
const val SP_SERVER_TIME_TOLERANCE = "server_time_tolerance" 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_PUBLIC_KEY = "server_public_key"
const val SP_SERVER_PRIVATE_KEY = "server_private_key" const val SP_SERVER_PRIVATE_KEY = "server_private_key"
const val SP_SERVER_WEB_PATH = "server_web_path" 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_SERVER_CONFIG = "server_config"
const val SP_CLIENT_SAFETY_MEASURES = "client_safety_measures" const val SP_CLIENT_SAFETY_MEASURES = "client_safety_measures"
const val SP_CLIENT_SIGN_KEY = "client_sign_key" const val SP_CLIENT_SIGN_KEY = "client_sign_key"
var CLIENT_FRAGMENT_LIST = listOf( var CLIENT_FRAGMENT_LIST = listOf(
PageInfo( PageInfo(
getString(R.string.api_clone), getString(R.string.api_clone),

View File

@ -40,6 +40,14 @@ class HttpServerUtils private constructor() {
MMKVUtils.put(SP_SERVER_SAFETY_MEASURES, safetyMeasures) 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公钥 //服务端RSA公钥
@JvmStatic @JvmStatic
var serverPublicKey: String? 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" style="@style/settingBarStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="vertical"
android:paddingEnd="10dp"
tools:ignore="RtlSymmetry">
<TextView <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/safety_measures" android:gravity="center_vertical"
android:textStyle="bold" /> 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 <RadioGroup
android:id="@+id/rg_safety_measures" android:id="@+id/rg_safety_measures"
android:layout_width="wrap_content" style="@style/rg_style"
android:layout_height="wrap_content"
android:layout_marginStart="3dp"
android:orientation="horizontal"> android:orientation="horizontal">
<RadioButton <RadioButton
android:id="@+id/rb_safety_measures_none" android:id="@+id/rb_safety_measures_none"
android:layout_width="wrap_content" style="@style/rg_rb_style"
android:layout_height="wrap_content"
android:checked="true" android:checked="true"
android:text="@string/safety_measures_none" android:text="@string/safety_measures_none" />
android:textSize="11sp" />
<RadioButton <RadioButton
android:id="@+id/rb_safety_measures_sign" android:id="@+id/rb_safety_measures_sign"
android:layout_width="wrap_content" style="@style/rg_rb_style"
android:layout_height="wrap_content" android:text="@string/safety_measures_sign" />
android:text="@string/safety_measures_sign"
android:textSize="11sp" />
<RadioButton <RadioButton
android:id="@+id/rb_safety_measures_rsa" android:id="@+id/rb_safety_measures_rsa"
android:layout_width="wrap_content" style="@style/rg_rb_style"
android:layout_height="wrap_content" android:text="@string/safety_measures_rsa" />
android:text="@string/safety_measures_encrypt"
android:textSize="11sp" /> <RadioButton
android:id="@+id/rb_safety_measures_sm4"
style="@style/rg_rb_style"
android:text="@string/safety_measures_sm4" />
</RadioGroup> </RadioGroup>

View File

@ -137,42 +137,57 @@
style="@style/settingBarStyle" style="@style/settingBarStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="vertical"
android:paddingEnd="10dp"
tools:ignore="RtlSymmetry">
<TextView <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/safety_measures" android:gravity="center_vertical"
android:textStyle="bold" /> 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 <RadioGroup
android:id="@+id/rg_safety_measures" android:id="@+id/rg_safety_measures"
android:layout_width="wrap_content" style="@style/rg_style"
android:layout_height="wrap_content"
android:layout_marginStart="3dp"
android:orientation="horizontal"> android:orientation="horizontal">
<RadioButton <RadioButton
android:id="@+id/rb_safety_measures_none" android:id="@+id/rb_safety_measures_none"
android:layout_width="wrap_content" style="@style/rg_rb_style"
android:layout_height="wrap_content"
android:checked="true" android:checked="true"
android:text="@string/safety_measures_none" android:text="@string/safety_measures_none" />
android:textSize="11sp" />
<RadioButton <RadioButton
android:id="@+id/rb_safety_measures_sign" android:id="@+id/rb_safety_measures_sign"
android:layout_width="wrap_content" style="@style/rg_rb_style"
android:layout_height="wrap_content" android:text="@string/safety_measures_sign" />
android:text="@string/safety_measures_sign"
android:textSize="11sp" />
<RadioButton <RadioButton
android:id="@+id/rb_safety_measures_rsa" android:id="@+id/rb_safety_measures_rsa"
android:layout_width="wrap_content" style="@style/rg_rb_style"
android:layout_height="wrap_content" android:text="@string/safety_measures_rsa" />
android:text="@string/safety_measures_encrypt"
android:textSize="11sp" /> <RadioButton
android:id="@+id/rb_safety_measures_sm4"
style="@style/rg_rb_style"
android:text="@string/safety_measures_sm4" />
</RadioGroup> </RadioGroup>
@ -365,6 +380,47 @@
</LinearLayout> </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 <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -608,7 +664,8 @@
<LinearLayout <LinearLayout
style="@style/settingBarStyle" style="@style/settingBarStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
tools:ignore="TooManyViews">
<LinearLayout <LinearLayout
android:layout_width="0dp" 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="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="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="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">Server Url</string>
<string name="service_address_hint">E.g: http://127.0.0.1:5000</string> <string name="service_address_hint">E.g: http://127.0.0.1:5000</string>
<string name="features_list">Features List</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="auto_clean_logs_tips">0=disabled, scan when battery change</string>
<string name="day">Day</string> <string name="day">Day</string>
<string name="safety_measures">Safety Measures</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_none">None</string>
<string name="safety_measures_sign">Sign</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="web_path_tips">See Github Wiki, download to Download directory</string>
<string name="time_tolerance">Time Tolerance</string> <string name="time_tolerance">Time Tolerance</string>
<string name="time_tolerance_tips">Minimize time tolerance to avoid request replay attacks</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">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="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="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> </resources>

View File

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

View File

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