初始提交

main
shisaiqun 2 years ago
parent 36aef16197
commit 817baa355d
  1. 48
      .gitignore
  2. 1
      app/.gitignore
  3. 43
      app/build.gradle
  4. 21
      app/proguard-rules.pro
  5. 26
      app/src/androidTest/java/cn/org/landcloud/survey/ExampleInstrumentedTest.java
  6. 35
      app/src/main/AndroidManifest.xml
  7. BIN
      app/src/main/assets/landcloud_demo.db
  8. BIN
      app/src/main/assets/phone_1.jpg
  9. BIN
      app/src/main/assets/phone_panoramic_1.jpg
  10. BIN
      app/src/main/assets/phone_video_1.mp4
  11. BIN
      app/src/main/assets/photo_uav_1658133414992.jpg
  12. BIN
      app/src/main/assets/photo_uav_1658133423647_panoramic.jpg
  13. 156
      app/src/main/java/cn/org/landcloud/survey/MainActivity.java
  14. 54
      app/src/main/java/cn/org/landcloud/survey/data/DBInfoDao.java
  15. 53
      app/src/main/java/cn/org/landcloud/survey/data/DCHSXXDao.java
  16. 476
      app/src/main/java/cn/org/landcloud/survey/data/DataRepositories.java
  17. 52
      app/src/main/java/cn/org/landcloud/survey/data/FJDao.java
  18. 54
      app/src/main/java/cn/org/landcloud/survey/data/JMXXDao.java
  19. 53
      app/src/main/java/cn/org/landcloud/survey/data/KZXXYSJDao.java
  20. 83
      app/src/main/java/cn/org/landcloud/survey/data/LandSurveyDatabase.java
  21. 54
      app/src/main/java/cn/org/landcloud/survey/data/TBJBXXDao.java
  22. 87
      app/src/main/java/cn/org/landcloud/survey/data/bean/DBInfo.java
  23. 89
      app/src/main/java/cn/org/landcloud/survey/data/bean/DCHSXX.java
  24. 395
      app/src/main/java/cn/org/landcloud/survey/data/bean/FJ.java
  25. 91
      app/src/main/java/cn/org/landcloud/survey/data/bean/JMXX.java
  26. 166
      app/src/main/java/cn/org/landcloud/survey/data/bean/KZXXYSJ.java
  27. 192
      app/src/main/java/cn/org/landcloud/survey/data/bean/TBJBXX.java
  28. 54
      app/src/main/java/cn/org/landcloud/survey/util/CloseUtils.java
  29. 10
      app/src/main/java/cn/org/landcloud/survey/util/Constants.java
  30. 707
      app/src/main/java/cn/org/landcloud/survey/util/FileIOUtils.java
  31. 43
      app/src/main/java/cn/org/landcloud/survey/util/TimeConstants.java
  32. 1650
      app/src/main/java/cn/org/landcloud/survey/util/TimeUtils.java
  33. 31
      app/src/main/java/cn/org/landcloud/survey/util/Utils.java
  34. 30
      app/src/main/res/drawable-v24/ic_launcher_foreground.xml
  35. 170
      app/src/main/res/drawable/ic_launcher_background.xml
  36. 71
      app/src/main/res/layout/activity_main.xml
  37. 5
      app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  38. 5
      app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  39. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.webp
  40. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
  41. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.webp
  42. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
  43. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.webp
  44. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
  45. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
  46. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
  47. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
  48. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
  49. 16
      app/src/main/res/values-night/themes.xml
  50. 10
      app/src/main/res/values/colors.xml
  51. 3
      app/src/main/res/values/strings.xml
  52. 16
      app/src/main/res/values/themes.xml
  53. 13
      app/src/main/res/xml/backup_rules.xml
  54. 19
      app/src/main/res/xml/data_extraction_rules.xml
  55. 17
      app/src/test/java/cn/org/landcloud/survey/ExampleUnitTest.java
  56. 5
      build.gradle
  57. 21
      gradle.properties
  58. BIN
      gradle/wrapper/gradle-wrapper.jar
  59. 6
      gradle/wrapper/gradle-wrapper.properties
  60. 185
      gradlew
  61. 89
      gradlew.bat
  62. 17
      settings.gradle
  63. 1
      ssl/.gitignore
  64. 21
      ssl/build.gradle
  65. 128
      ssl/src/main/java/cn/org/landcloud/security/Base64.java
  66. 617
      ssl/src/main/java/cn/org/landcloud/security/Util.java
  67. 107
      ssl/src/main/java/cn/org/landcloud/security/sm2/Cipher.java
  68. 67
      ssl/src/main/java/cn/org/landcloud/security/sm2/SM2.java
  69. 208
      ssl/src/main/java/cn/org/landcloud/security/sm2/SM2EncDecUtils.java
  70. 179
      ssl/src/main/java/cn/org/landcloud/security/sm2/SM2Factory.java
  71. 42
      ssl/src/main/java/cn/org/landcloud/security/sm2/SM2KeyVO.java
  72. 28
      ssl/src/main/java/cn/org/landcloud/security/sm2/SM2Result.java
  73. 116
      ssl/src/main/java/cn/org/landcloud/security/sm2/SM2SignVO.java
  74. 166
      ssl/src/main/java/cn/org/landcloud/security/sm2/SM2SignVerUtils.java
  75. 328
      ssl/src/main/java/cn/org/landcloud/security/sm3/SM3.java
  76. 90
      ssl/src/main/java/cn/org/landcloud/security/sm3/SM3Utils.java
  77. 315
      ssl/src/main/java/cn/org/landcloud/security/sm4/SM4.java
  78. 173
      ssl/src/main/java/cn/org/landcloud/security/sm4/SM4Utils.java
  79. 19
      ssl/src/main/java/cn/org/landcloud/security/sm4/SM4_Context.java
  80. 131
      ssl/src/main/java/cn/org/landcloud/security/test/SecurityTest.java
  81. 219
      ssl/src/main/java/cn/org/landcloud/security/test/SecurityTestAll.java

48
.gitignore vendored

@ -1,35 +1,15 @@
# ---> Android
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Log/OS Files
*.log
# Android Studio generated files and folders
captures/
.externalNativeBuild/
.cxx/
*.apk
output.json
# IntelliJ
*.iml
.idea/
misc.xml
deploymentTargetDropDown.xml
render.experimental.xml
# Keystore files
*.jks
*.keystore
# Google Services (e.g. APIs or Firebase)
google-services.json
# Android Profiling
*.hprof
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

1
app/.gitignore vendored

@ -0,0 +1 @@
/build

@ -0,0 +1,43 @@
plugins {
id 'com.android.application'
}
android {
namespace 'cn.org.landcloud.survey'
compileSdk 32
defaultConfig {
applicationId "cn.org.landcloud.survey"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation project(path: ':ssl')
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation "androidx.room:room-runtime:2.2.6"
annotationProcessor "androidx.room:room-compiler:2.2.6"
}

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

@ -0,0 +1,26 @@
package cn.org.landcloud.survey;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("cn.org.landcloud.survey", appContext.getPackageName());
}
}

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:requestLegacyExternalStorage="true"
android:theme="@style/Theme.Landsurvey"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

@ -0,0 +1,156 @@
package cn.org.landcloud.survey;
import static cn.org.landcloud.survey.data.DataRepositories.RELATIVE_FJ_DIR;
import static cn.org.landcloud.survey.data.DataRepositories.RELATIVE_PATH;
import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import cn.org.landcloud.security.Util;
import cn.org.landcloud.security.sm2.SM2EncDecUtils;
import cn.org.landcloud.security.sm2.SM2KeyVO;
import cn.org.landcloud.security.sm2.SM2SignVO;
import cn.org.landcloud.security.sm2.SM2SignVerUtils;
import cn.org.landcloud.security.sm3.SM3Utils;
import cn.org.landcloud.survey.data.DataRepositories;
import cn.org.landcloud.survey.data.LandSurveyDatabase;
import cn.org.landcloud.survey.util.Constants;
import cn.org.landcloud.survey.util.FileIOUtils;
import cn.org.landcloud.survey.util.Utils;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CODE = 0x1000;
private TextView logView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
checkPermissions();
}
private void checkPermissions() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// 申请权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
}
}
}
private void initView() {
logView = findViewById(R.id.log_tv);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_CODE: {
if (grantResults.length > 0) {
for (int grantresult : grantResults) {
if (grantresult != PackageManager.PERMISSION_GRANTED) {
new AlertDialog.Builder(MainActivity.this).setTitle("系统提示")
.setMessage("有部分权限授权失败,请通过后台应用设置重新授权!")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {//确定按钮的响应事件
finish();
}
}).show();
return;
}
}
}
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
logView.setText("");
}
/**
* @param view
*/
public void createSSL(View view) {
SM2KeyVO result = SM2EncDecUtils.generateKeyPair();
logView.append("--产生SM2密钥--:\n");
logView.append("公钥:" + result.getPubHexInSoft() + "\n");
logView.append("私钥:" + result.getPriHexInSoft() + "\n");
}
/**
* @param view
*/
public void initData(View view) {
logView.append("--开始生成样例成果db包--:\n");
DataRepositories.getInstance().initData(this);
File file = new File(Environment.getExternalStorageDirectory(), RELATIVE_PATH);
LandSurveyDatabase.getInstance().destroy();
logView.append("--样例成果db包生成完成,路径为--:" + file.getPath() + "\n");
}
/**
* @param view
*/
public void getJYM(View view) {
logView.append("--开始生成附件信息签名--:\n");
File file = new File(Environment.getExternalStorageDirectory(),RELATIVE_FJ_DIR+"phone_1.jpg");
StringBuffer stringBuffer = new StringBuffer();
try {
String fjhxz = SM3Utils.sm3(file);
stringBuffer.append(fjhxz).append(",");
} catch (IOException e) {
e.printStackTrace();
}
// FJHXZ,PSSJ,Longitude,Latitude,PSFYJ,PSJD,PSHGJ,PSRY,ZSDM
stringBuffer.append("2022-10-18 15:42:56,119.98547,30.277615,41.0,239.0,2.0,test,1001");
String jym = Utils.makeJYM(stringBuffer.toString(),Constants.TEST_PRIVATEKEY);
logView.append("--附件信息签名--:" + jym + "\n");
}
/**
* @param view
*/
public void getHash(View view) {
logView.append("--开始生成图片Hash--:\n");
File file = new File(Environment.getExternalStorageDirectory(), RELATIVE_FJ_DIR+"phone_1.jpg");
if (!file.isFile() || !file.exists()) {
logView.append("没有找到文件:" + file.getPath() + "\n");
return;
}
try {
String hashCode = SM3Utils.sm3(file);
logView.append("--Hash值--:" + hashCode + "\n");
} catch (IOException e) {
e.printStackTrace();
logView.append("--生成Hash值失败--:" + e.getMessage() + "\n");
}
}
}

@ -0,0 +1,54 @@
package cn.org.landcloud.survey.data;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Update;
import java.util.List;
import cn.org.landcloud.survey.data.bean.DBInfo;
import cn.org.landcloud.survey.data.bean.FJ;
@Dao
public interface DBInfoDao {
/**
* 插入一条新的附件
* 如插入时发生冲突处理方式为插入一个新的对象
*
* @param dbInfo
* @return
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insertDBInfo(DBInfo dbInfo);
@Update
int updateDBInfo(DBInfo dbInfo);
@Delete
int deleteDBInfo(DBInfo dbInfo);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertDBInfo(DBInfo... dbInfo);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertDBInfo(List<DBInfo> dbInfos);
@Update
void updateDBInfo(DBInfo... dbInfo);
@Update
void updateDBInfo(List<DBInfo> dbInfo);
@Delete
void deleteDBInfo(DBInfo... dbInfo);
@Delete
void deleteDBInfo(List<DBInfo> dbInfo);
}

@ -0,0 +1,53 @@
package cn.org.landcloud.survey.data;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Update;
import java.util.List;
import cn.org.landcloud.survey.data.bean.DCHSXX;
@Dao
public interface DCHSXXDao {
/**
* 插入一条新的附件
* 如插入时发生冲突处理方式为插入一个新的对象
*
* @param dchsxx
* @return
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insertDCHSXX(DCHSXX dchsxx);
@Update
int updateDCHSXX(DCHSXX dchsxx);
@Delete
int deleteDCHSXX(DCHSXX dchsxx);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertDCHSXX(DCHSXX... dchsxx);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertDCHSXX(List<DCHSXX> dchsxxs);
@Update
void updateDCHSXX(DCHSXX... dchsxx);
@Update
void updateDCHSXX(List<DCHSXX> dchsxx);
@Delete
void deleteDCHSXX(DCHSXX... dchsxx);
@Delete
void deleteDCHSXX(List<DCHSXX> fj);
}

@ -0,0 +1,476 @@
package cn.org.landcloud.survey.data;
import static cn.org.landcloud.survey.util.Constants.CERT_ORG_CODE;
import static cn.org.landcloud.survey.util.Constants.TEST_CER;
import static cn.org.landcloud.survey.util.Constants.TEST_CERT_ORG_PUBLICKEY;
import static cn.org.landcloud.survey.util.Constants.TEST_PUBLICKEY;
import android.content.Context;
import android.os.Environment;
import androidx.annotation.NonNull;
import org.json.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import cn.org.landcloud.security.Util;
import cn.org.landcloud.security.sm2.SM2SignVO;
import cn.org.landcloud.security.sm2.SM2SignVerUtils;
import cn.org.landcloud.security.sm3.SM3Utils;
import cn.org.landcloud.survey.util.Constants;
import cn.org.landcloud.survey.util.FileIOUtils;
import cn.org.landcloud.survey.util.TimeUtils;
import cn.org.landcloud.survey.util.Utils;
import cn.org.landcloud.survey.data.bean.DBInfo;
import cn.org.landcloud.survey.data.bean.DCHSXX;
import cn.org.landcloud.survey.data.bean.FJ;
import cn.org.landcloud.survey.data.bean.JMXX;
import cn.org.landcloud.survey.data.bean.KZXXYSJ;
import cn.org.landcloud.survey.data.bean.TBJBXX;
public class DataRepositories {
private static DataRepositories instance;
public static final String DB_NAME = "landcloud_demo.db";
public static final String FJ_NAME_1 = "phone_1.jpg";
public static final String FJ_NAME_2 = "phone_panoramic_1.jpg";
public static final String FJ_NAME_3 = "phone_video_1.mp4";
public static final String FJ_NAME_4 = "photo_uav_1658133414992.jpg";
public static final String FJ_NAME_5 = "photo_uav_1658133423647_panoramic.jpg";
public static final String RELATIVE_PATH = "testData/"+DB_NAME;
public static final String RELATIVE_FJ_DIR = "testData/fj/";
private DataRepositories() {
}
public static DataRepositories getInstance() {
if (instance == null) {
synchronized (DataRepositories.class) {
instance = new DataRepositories();
}
}
return instance;
}
public void initData(@NonNull Context context) {
initDb(context);
File file = new File(Environment.getExternalStorageDirectory(),RELATIVE_PATH);
LandSurveyDatabase.init(context,file.getPath());
// LandSurveyDatabase.getInstance().clearAllTables();
initTestData(context);
}
private void initTestData(@NonNull Context context) {
//测试扩展信息
KZXXYSJ jbxx_dlbm = new KZXXYSJ();
jbxx_dlbm.setBSM(1);
jbxx_dlbm.setTBLX("JCTB");
jbxx_dlbm.setZDMC("DLBM");
jbxx_dlbm.setZDBM("地类编码");
jbxx_dlbm.setZDMS("地类编码");
jbxx_dlbm.setZDLX("TEXT");
jbxx_dlbm.setZDCD(20);
jbxx_dlbm.setSFBT("M");
jbxx_dlbm.setKZXXLX("JBXX");
KZXXYSJ jbxx_dlmc = new KZXXYSJ();
jbxx_dlmc.setBSM(2);
jbxx_dlmc.setTBLX("JCTB");
jbxx_dlmc.setZDMC("DLMC");
jbxx_dlmc.setZDBM("地类名称");
jbxx_dlmc.setZDMS("地类名称");
jbxx_dlmc.setZDLX("TEXT");
jbxx_dlmc.setZDCD(20);
jbxx_dlmc.setSFBT("O");
jbxx_dlmc.setKZXXLX("JBXX");
KZXXYSJ dcxx_bglx = new KZXXYSJ();
dcxx_bglx.setBSM(3);
dcxx_bglx.setTBLX("JCTB");
dcxx_bglx.setZDMC("BGLX");
dcxx_bglx.setZDBM("变更类型");
dcxx_bglx.setZDMS("变更类型");
dcxx_bglx.setZDLX("TEXT");
dcxx_bglx.setZDCD(20);
dcxx_bglx.setSFBT("O");
dcxx_bglx.setKZXXLX("DCXX");
KZXXYSJ dcxx_bgfw = new KZXXYSJ();
dcxx_bgfw.setBSM(4);
dcxx_bgfw.setTBLX("JCTB");
dcxx_bgfw.setZDMC("BGFW");
dcxx_bgfw.setZDBM("变更范围");
dcxx_bgfw.setZDMS("变更范围");
dcxx_bgfw.setZDLX("TEXT");
dcxx_bgfw.setZDCD(20);
dcxx_bgfw.setSFBT("O");
dcxx_bgfw.setKZXXLX("DCXX");
LandSurveyDatabase.getInstance().kzxxysjDao().insertKZXXYSJ(jbxx_dlbm,jbxx_dlmc,dcxx_bglx,dcxx_bgfw);
//测试地块信息
TBJBXX tbjbxx = new TBJBXX();
tbjbxx.setBSM("8fd575622ffd45ff8ae9fba0b9c5ec20");
tbjbxx.setTBLX("JCTB");
tbjbxx.setXZQDM("110101");
tbjbxx.setXMC("余杭");
tbjbxx.setTBBH("CS110101201600000100099");
tbjbxx.setTBMC("1");
tbjbxx.setTBMJ(9.43);
tbjbxx.setXZB(40498699.025);
tbjbxx.setYZB(3350604.784);
tbjbxx.setBZ("");
HashMap<String,Object> jbxxMap = new HashMap<>();
jbxxMap.put("DLBM","03B2");
jbxxMap.put("DLMC","工地草被");
JSONObject jbxxKZXXJSON = new JSONObject(jbxxMap);
tbjbxx.setKZXX(jbxxKZXXJSON.toString());
tbjbxx.setTBFW("MULTIPOLYGON (((40498699.02535 3350604.7848, 40498697.04095 3350528.7169499993, 40498781.7078 3350530.70135, 40498780.3849 3350606.1077500004, 40498699.02535 3350604.7848)))");
LandSurveyDatabase.getInstance().tbjbxxDao().insertTBJBXX(tbjbxx);
//测试调查信息
DCHSXX dchsxx = new DCHSXX();
dchsxx.setDCRY("张三");
dchsxx.setDCSJ("2022-10-14 10:12:13");
HashMap<String,Object> dcxxMap = new HashMap<>();
dcxxMap.put("BGFW","部分变更");
dcxxMap.put("BGLX","0");
JSONObject dcxxKZXXJson = new JSONObject(dcxxMap);
dchsxx.setKZXX(dcxxKZXXJson.toString());
dchsxx.setWYHSQK("违法建筑");
dchsxx.setTBBSM("8fd575622ffd45ff8ae9fba0b9c5ec20");
LandSurveyDatabase.getInstance().dchsxxDao().insertDCHSXX(dchsxx);
DBInfo dbInfo = new DBInfo();
dbInfo.setCreatetime(TimeUtils.getNowString());
dbInfo.setUpdatetime(TimeUtils.getNowString());
dbInfo.setDescription("测试数据包");
dbInfo.setCreateuser("admin");
dbInfo.setVersion("1.0");
LandSurveyDatabase.getInstance().dbInfoDao().insertDBInfo(dbInfo);
JMXX jmxx = new JMXX();
jmxx.setZSDM("1001");
jmxx.setSZZS(TEST_CER);
jmxx.setZSBFJGDM(CERT_ORG_CODE);
jmxx.setZSBFJGGY(TEST_CERT_ORG_PUBLICKEY);
LandSurveyDatabase.getInstance().jmxxDao().insertJMXX(jmxx);
//测试附件
FJ fj_phone_normal = new FJ();
fj_phone_normal.setBSM("1");
fj_phone_normal.setTBLX("JCTB");
fj_phone_normal.setTBBSM("8fd575622ffd45ff8ae9fba0b9c5ec20");
fj_phone_normal.setXZQDM("110101");
fj_phone_normal.setFJMC("110101");
fj_phone_normal.setFJLX("0");
fj_phone_normal.setPSTZ("J");
File file = new File(Environment.getExternalStorageDirectory(),RELATIVE_FJ_DIR+"phone_1.jpg");
fj_phone_normal.setFJ(FileIOUtils.readFile2BytesByChannel(file));
try {
fj_phone_normal.setFJHXZ(SM3Utils.sm3(file));
} catch (IOException e) {
e.printStackTrace();
}
fj_phone_normal.setPSSJ("2022-10-18 15:42:56");
//无人机时必填
// fj_phone_normal.setJDGD(null);
fj_phone_normal.setLongitude(119.9854700);
fj_phone_normal.setLatitude(30.2776150);
fj_phone_normal.setPSFYJ(41d);
fj_phone_normal.setPSJD(239d);
fj_phone_normal.setPSHGJ(2d);
fj_phone_normal.setPSJJ(27d);
fj_phone_normal.setXDGD(1.50d);
fj_phone_normal.setFJYSKD(1920);
fj_phone_normal.setFJYSGD(1080);
fj_phone_normal.setPSRY("test");
//为视频时必填
// fj_phone_normal.setSPKZXX("");
fj_phone_normal.setZSDM("1001");
//附件信息上链时返回的交易ID
// fj_phone_normal.setQKLDM(null);
//校验码
StringBuffer content = new StringBuffer();
// FJHXZ,PSSJ,Longitude,Latitude,PSFYJ,PSJD,PSHGJ,PSRY,ZSDM
content.append(fj_phone_normal.getFJHXZ()).append(",");
content.append(fj_phone_normal.getPSSJ()).append(",");
content.append(fj_phone_normal.getLongitude()).append(",");
content.append(fj_phone_normal.getLatitude()).append(",");
content.append(fj_phone_normal.getPSFYJ()).append(",");
content.append(fj_phone_normal.getPSJD()).append(",");
content.append(fj_phone_normal.getPSHGJ()).append(",");
content.append(fj_phone_normal.getPSRY()).append(",");
content.append(fj_phone_normal.getZSDM());
String jym = Utils.makeJYM(content.toString(),Constants.TEST_PRIVATEKEY);
fj_phone_normal.setJYM(jym);
// SM2SignVO verify = SM2SignVerUtils.VerifySignSM2(Util.hexStringToBytes(TEST_PUBLICKEY), SM3Utils.sm3(content.toString()).getBytes(StandardCharsets.UTF_8), Util.hexStringToBytes(jym));
// System.out.println("验签得到的R值:"+verify.getVerify_r());
// System.err.println("\n验签结果" +verify.isVerify());
FJ fj_phone_panoramic = new FJ();
fj_phone_panoramic.setBSM("2");
fj_phone_panoramic.setTBLX("JCTB");
fj_phone_panoramic.setTBBSM("8fd575622ffd45ff8ae9fba0b9c5ec21");
fj_phone_panoramic.setXZQDM("110101");
fj_phone_panoramic.setFJMC("110101");
fj_phone_panoramic.setFJLX("2");
fj_phone_panoramic.setPSTZ("J");
file = new File(Environment.getExternalStorageDirectory(),RELATIVE_FJ_DIR+"phone_panoramic_1.jpg");
fj_phone_panoramic.setFJ(FileIOUtils.readFile2BytesByChannel(file));
try {
fj_phone_panoramic.setFJHXZ(SM3Utils.sm3(file));
} catch (IOException e) {
e.printStackTrace();
}
fj_phone_panoramic.setPSSJ("2022:10:18 15:43:50");
//无人机时必填
// fj_phone_panoramic.setJDGD(null);
fj_phone_panoramic.setLongitude(119.9854813);
fj_phone_panoramic.setLatitude(30.2775860);
fj_phone_panoramic.setPSFYJ(26d);
fj_phone_panoramic.setPSJD(22d);
fj_phone_panoramic.setPSHGJ(-88d);
fj_phone_panoramic.setPSJJ(27d);
fj_phone_panoramic.setXDGD(1.50d);
fj_phone_panoramic.setFJYSKD(4096);
fj_phone_panoramic.setFJYSGD(2048);
fj_phone_panoramic.setPSRY("test");
//为视频时必填
// fj_phone_panoramic.setSPKZXX("");
fj_phone_panoramic.setZSDM("1001");
//附件信息上链时返回的交易ID
// fj_phone_panoramic.setQKLDM(null);
//校验码
content = new StringBuffer();
// FJHXZ,PSSJ,Longitude,Latitude,PSFYJ,PSJD,PSHGJ,PSRY,ZSDM
content.append(fj_phone_panoramic.getFJHXZ()).append(",");
content.append(fj_phone_panoramic.getPSSJ()).append(",");
content.append(fj_phone_panoramic.getLongitude()).append(",");
content.append(fj_phone_panoramic.getLatitude()).append(",");
content.append(fj_phone_panoramic.getPSFYJ()).append(",");
content.append(fj_phone_panoramic.getPSJD()).append(",");
content.append(fj_phone_panoramic.getPSHGJ()).append(",");
content.append(fj_phone_panoramic.getPSRY()).append(",");
content.append(fj_phone_panoramic.getZSDM());
fj_phone_panoramic.setJYM(Utils.makeJYM(content.toString(),Constants.TEST_PRIVATEKEY));
FJ fj_uav_normal = new FJ();
fj_uav_normal.setBSM("3");
fj_uav_normal.setTBLX("JCTB");
fj_uav_normal.setTBBSM("8fd575622ffd45ff8ae9fba0b9c5ec23");
fj_uav_normal.setXZQDM("110101");
fj_uav_normal.setFJMC("110101");
fj_uav_normal.setFJLX("1");
fj_uav_normal.setPSTZ("J");
file = new File(Environment.getExternalStorageDirectory(),RELATIVE_FJ_DIR+"photo_uav_1658133414992.jpg");
fj_uav_normal.setFJ(FileIOUtils.readFile2BytesByChannel(file));
try {
fj_uav_normal.setFJHXZ(SM3Utils.sm3(file));
} catch (IOException e) {
e.printStackTrace();
}
fj_uav_normal.setPSSJ("2022:07:18 16:35:21");
//无人机时必填
fj_uav_normal.setJDGD(-19d);
fj_uav_normal.setLongitude(119.9855061);
fj_uav_normal.setLatitude(30.2774821);
fj_uav_normal.setPSFYJ(-66d);
fj_uav_normal.setPSJD(337d);
fj_uav_normal.setPSHGJ(0d);
fj_uav_normal.setPSJJ(24d);
fj_uav_normal.setXDGD(111.00d);
fj_uav_normal.setFJYSKD(4000);
fj_uav_normal.setFJYSGD(2250);
fj_uav_normal.setPSRY("kmap");
//为视频时必填
// fj_uav_normal.setSPKZXX("");
fj_uav_normal.setZSDM("1001");
//附件信息上链时返回的交易ID
// fj_uav_normal.setQKLDM(null);
//校验码
content = new StringBuffer();
// FJHXZ,PSSJ,Longitude,Latitude,PSFYJ,PSJD,PSHGJ,PSRY,ZSDM
content.append(fj_uav_normal.getFJHXZ()).append(",");
content.append(fj_uav_normal.getPSSJ()).append(",");
content.append(fj_uav_normal.getLongitude()).append(",");
content.append(fj_uav_normal.getLatitude()).append(",");
content.append(fj_uav_normal.getPSFYJ()).append(",");
content.append(fj_uav_normal.getPSJD()).append(",");
content.append(fj_uav_normal.getPSHGJ()).append(",");
content.append(fj_uav_normal.getPSRY()).append(",");
content.append(fj_uav_normal.getZSDM());
fj_uav_normal.setJYM(Utils.makeJYM(content.toString(),Constants.TEST_PRIVATEKEY));
FJ fj_uav_panoramic = new FJ();
fj_uav_panoramic.setBSM("4");
fj_uav_panoramic.setTBLX("JCTB");
fj_uav_panoramic.setTBBSM("8fd575622ffd45ff8ae9fba0b9c5ec24");
fj_uav_panoramic.setXZQDM("110101");
fj_uav_panoramic.setFJMC("110101");
fj_uav_panoramic.setFJLX("3");
fj_uav_panoramic.setPSTZ("J");
file = new File(Environment.getExternalStorageDirectory(),RELATIVE_FJ_DIR+"photo_uav_1658133423647_panoramic.jpg");
fj_uav_panoramic.setFJ(FileIOUtils.readFile2BytesByChannel(file));
try {
fj_uav_panoramic.setFJHXZ(SM3Utils.sm3(file));
} catch (IOException e) {
e.printStackTrace();
}
fj_uav_panoramic.setPSSJ("2022:07:18 16:36:44");
//无人机时必填
fj_uav_panoramic.setJDGD(-19d);
fj_uav_panoramic.setLongitude(119.9855061);
fj_uav_panoramic.setLatitude(30.2774821);
fj_uav_panoramic.setPSFYJ(-89d);
fj_uav_panoramic.setPSJD(337d);
fj_uav_panoramic.setPSHGJ(0d);
fj_uav_panoramic.setPSJJ(24d);
fj_uav_panoramic.setXDGD(112.00d);
fj_uav_panoramic.setFJYSKD(4096);
fj_uav_panoramic.setFJYSGD(2048);
fj_uav_panoramic.setPSRY("kmap");
//为视频时必填
// fj_uav_panoramic.setSPKZXX("");
fj_uav_panoramic.setZSDM("1001");
//附件信息上链时返回的交易ID
// fj_uav_panoramic.setQKLDM(null);
//校验码
content = new StringBuffer();
// FJHXZ,PSSJ,Longitude,Latitude,PSFYJ,PSJD,PSHGJ,PSRY,ZSDM
content.append(fj_uav_panoramic.getFJHXZ()).append(",");
content.append(fj_uav_panoramic.getPSSJ()).append(",");
content.append(fj_uav_panoramic.getLongitude()).append(",");
content.append(fj_uav_panoramic.getLatitude()).append(",");
content.append(fj_uav_panoramic.getPSFYJ()).append(",");
content.append(fj_uav_panoramic.getPSJD()).append(",");
content.append(fj_uav_panoramic.getPSHGJ()).append(",");
content.append(fj_uav_panoramic.getPSRY()).append(",");
content.append(fj_uav_panoramic.getZSDM());
fj_uav_panoramic.setJYM(Utils.makeJYM(content.toString(),Constants.TEST_PRIVATEKEY));
FJ fj_video = new FJ();
fj_video.setBSM("5");
fj_video.setTBLX("JCTB");
fj_video.setTBBSM("8fd575622ffd45ff8ae9fba0b9c5ec25");
fj_video.setXZQDM("110101");
fj_video.setFJMC("110101");
fj_video.setFJLX("4");
fj_video.setPSTZ("J");
file = new File(Environment.getExternalStorageDirectory(),RELATIVE_FJ_DIR+"phone_video_1.mp4");
fj_video.setFJ(FileIOUtils.readFile2BytesByChannel(file));
try {
fj_video.setFJHXZ(SM3Utils.sm3(file));
} catch (IOException e) {
e.printStackTrace();
}
fj_video.setPSSJ("2022-10-18 15:43:09");
//无人机时必填
// fj_video.setJDGD(null);
fj_video.setLongitude(119.9854736);
fj_video.setLatitude(30.2776146);
fj_video.setPSFYJ(15d);
fj_video.setPSJD(230d);
fj_video.setPSHGJ(0d);
fj_video.setPSJJ(27d);
fj_video.setXDGD(1.50d);
fj_video.setFJYSKD(480);
fj_video.setFJYSGD(360);
fj_video.setPSRY("test");
//为视频时必填
fj_video.setSPKZXX("[{\"position\":1,\"x\":119.9854736,\"y\":30.27761460,\"angel\":230,\"height\":1.5},{\"position\":2,\"x\":119.985474,\"y\":30.27761460,\"angel\":232,\"height\":1.5},{\"position\":3,\"x\":119.9854736,\"y\":30.27761460,\"angel\":220,\"height\":1.5},{\"position\":4,\"x\":119.9854736,\"y\":30.27761459,\"angel\":231,\"height\":1.5},{\"position\":5,\"x\":119.9854736,\"y\":30.27761459,\"angel\":237,\"height\":1.5},{\"position\":6,\"x\":119.9854736,\"y\":30.27761459,\"angel\":246,\"height\":1.5},{\"position\":7,\"x\":119.9854736,\"y\":30.27761460,\"angel\":235,\"height\":1.5},{\"position\":8,\"x\":119.9854736,\"y\":30.27761459,\"angel\":213,\"height\":1.5},{\"position\":9,\"x\":119.9854736,\"y\":30.27761459,\"angel\":254,\"height\":1.5}]");
fj_video.setZSDM("1001");
//附件信息上链时返回的交易ID
// fj_video.setQKLDM(null);
//校验码
content = new StringBuffer();
// FJHXZ,PSSJ,Longitude,Latitude,PSFYJ,PSJD,PSHGJ,PSRY,ZSDM
content.append(fj_video.getFJHXZ()).append(",");
content.append(fj_video.getPSSJ()).append(",");
content.append(fj_video.getLongitude()).append(",");
content.append(fj_video.getLatitude()).append(",");
content.append(fj_video.getPSFYJ()).append(",");
content.append(fj_video.getPSJD()).append(",");
content.append(fj_video.getPSHGJ()).append(",");
content.append(fj_video.getPSRY()).append(",");
content.append(fj_video.getZSDM());
fj_video.setJYM(Utils.makeJYM(content.toString(),Constants.TEST_PRIVATEKEY));
LandSurveyDatabase.getInstance().fjDao().insertFJ(fj_phone_normal,fj_phone_panoramic,fj_uav_normal,fj_uav_panoramic,fj_video);
// LandSurveyDatabase.getInstance().fjDao().insertFJ(fj_phone_normal,fj_phone_panoramic,fj_uav_normal);
}
public void initDb(@NonNull Context context) {
try {
InputStream is = context.getAssets().open(DB_NAME);
File file = new File(Environment.getExternalStorageDirectory(), RELATIVE_PATH);
if (!file.exists() || !file.isFile()) {
file.getParentFile().mkdir();
FileIOUtils.writeFileFromIS(file,is);
}
is = context.getAssets().open(FJ_NAME_1);
file = new File(Environment.getExternalStorageDirectory(), RELATIVE_FJ_DIR+FJ_NAME_1);
if (!file.exists() || !file.isFile()) {
file.getParentFile().mkdir();
FileIOUtils.writeFileFromIS(file,is);
}
is = context.getAssets().open(FJ_NAME_2);
file = new File(Environment.getExternalStorageDirectory(), RELATIVE_FJ_DIR+FJ_NAME_2);
if (!file.exists() || !file.isFile()) {
file.getParentFile().mkdir();
FileIOUtils.writeFileFromIS(file,is);
}
is = context.getAssets().open(FJ_NAME_3);
file = new File(Environment.getExternalStorageDirectory(), RELATIVE_FJ_DIR+FJ_NAME_3);
if (!file.exists() || !file.isFile()) {
file.getParentFile().mkdir();
FileIOUtils.writeFileFromIS(file,is);
}
is = context.getAssets().open(FJ_NAME_4);
file = new File(Environment.getExternalStorageDirectory(), RELATIVE_FJ_DIR+FJ_NAME_4);
if (!file.exists() || !file.isFile()) {
file.getParentFile().mkdir();
FileIOUtils.writeFileFromIS(file,is);
}
is = context.getAssets().open(FJ_NAME_5);
file = new File(Environment.getExternalStorageDirectory(), RELATIVE_FJ_DIR+FJ_NAME_5);
if (!file.exists() || !file.isFile()) {
file.getParentFile().mkdir();
FileIOUtils.writeFileFromIS(file,is);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}

@ -0,0 +1,52 @@
package cn.org.landcloud.survey.data;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Update;
import java.util.List;
import cn.org.landcloud.survey.data.bean.FJ;
@Dao
public interface FJDao {
/**
* 插入一条新的附件
* 如插入时发生冲突处理方式为插入一个新的对象
* @param fj
* @return
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insertFJ(FJ fj);
@Update
int updateFJ(FJ fj);
@Delete
int deleteFJ(FJ fj);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertFJ(FJ... fj);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertFJ(List<FJ> fjs);
@Update
void updateFJ(FJ... fj);
@Update
void updateFJ(List<FJ> fj);
@Delete
void deleteFJ(FJ... fj);
@Delete
void deleteFJ(List<FJ> fj);
}

@ -0,0 +1,54 @@
package cn.org.landcloud.survey.data;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Update;
import java.util.List;
import cn.org.landcloud.survey.data.bean.JMXX;
import cn.org.landcloud.survey.data.bean.KZXXYSJ;
@Dao
public interface JMXXDao {
/**
* 插入一条新的附件
* 如插入时发生冲突处理方式为插入一个新的对象
*
* @param kzxxysj
* @return
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insertJMXX(JMXX jmxx);
@Update
int updateJMXX(JMXX jmxx);
@Delete
int deleteJMXX(JMXX jmxx);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertKZXXYSJ(JMXX... jmxxs);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertJMXX(List<JMXX> jmxxList);
@Update
void updateJMXX(JMXX... jmxxs);
@Update
void updateJMXX(List<JMXX> jmxxList);
@Delete
void deleteJMXX(JMXX... jmxxs);
@Delete
void deleteJMXX(List<JMXX> jmxxList);
}

@ -0,0 +1,53 @@
package cn.org.landcloud.survey.data;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Update;
import java.util.List;
import cn.org.landcloud.survey.data.bean.KZXXYSJ;
@Dao
public interface KZXXYSJDao {
/**
* 插入一条新的附件
* 如插入时发生冲突处理方式为插入一个新的对象
*
* @param kzxxysj
* @return
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insertKZXXYSJ(KZXXYSJ kzxxysj);
@Update
int updateKZXXYSJ(KZXXYSJ kzxxysj);
@Delete
int deleteKZXXYSJ(KZXXYSJ kzxxysj);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertKZXXYSJ(KZXXYSJ... kzxxysjs);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertKZXXYSJ(List<KZXXYSJ> kzxxysjList);
@Update
void updateKZXXYSJ(KZXXYSJ... kzxxysjs);
@Update
void updateKZXXYSJ(List<KZXXYSJ> kzxxysjList);
@Delete
void deleteKZXXYSJ(KZXXYSJ... kzxxysjs);
@Delete
void deleteKZXXYSJ(List<KZXXYSJ> kzxxysjList);
}

@ -0,0 +1,83 @@
package cn.org.landcloud.survey.data;
import android.content.Context;
import android.text.TextUtils;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import cn.org.landcloud.survey.data.bean.DBInfo;
import cn.org.landcloud.survey.data.bean.DCHSXX;
import cn.org.landcloud.survey.data.bean.FJ;
import cn.org.landcloud.survey.data.bean.JMXX;
import cn.org.landcloud.survey.data.bean.KZXXYSJ;
import cn.org.landcloud.survey.data.bean.TBJBXX;
@Database(entities = {DBInfo.class, DCHSXX.class, FJ.class, TBJBXX.class, KZXXYSJ.class, JMXX.class},
version = 2, exportSchema = false)
public abstract class LandSurveyDatabase extends RoomDatabase {
public static final String TABLE_NAME = "WYHCFJ";
public static final String COLUMN_NAME_BSM = "F_ID";
public static final String COLUMN_NAME_CONTENT = "FJ";
private static String sDbPath = null;
private static volatile LandSurveyDatabase INSTANCE = null;
private static Context mContext;
/**
* 初始化AppDatabase参数
*
* @param context 上下文引用
* @param dbPath 数据库路径
*/
public static void init(Context context, String dbPath) {
mContext = context;
sDbPath = dbPath;
if (INSTANCE != null) {
INSTANCE.close();
INSTANCE = null;
}
}
public static LandSurveyDatabase getInstance() {
if (INSTANCE == null) {
synchronized (LandSurveyDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room
.databaseBuilder(mContext.getApplicationContext(), LandSurveyDatabase.class, sDbPath)
.allowMainThreadQueries()
.build();
}
}
}
return (INSTANCE);
}
public void destroy() {
if (INSTANCE != null) {
INSTANCE.close();
INSTANCE = null;
}
}
public abstract DBInfoDao dbInfoDao();
public abstract DCHSXXDao dchsxxDao();
public abstract FJDao fjDao();
public abstract KZXXYSJDao kzxxysjDao();
public abstract TBJBXXDao tbjbxxDao();
public abstract JMXXDao jmxxDao();
}

@ -0,0 +1,54 @@
package cn.org.landcloud.survey.data;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Update;
import java.util.List;
import cn.org.landcloud.survey.data.bean.KZXXYSJ;
import cn.org.landcloud.survey.data.bean.TBJBXX;
@Dao
public interface TBJBXXDao {
/**
* 插入一条新的附件
* 如插入时发生冲突处理方式为插入一个新的对象
*
* @param tbjbxx
* @return
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insertTBJBXX(TBJBXX tbjbxx);
@Update
int updateTBJBXX(TBJBXX tbjbxx);
@Delete
int deleteTBJBXX(TBJBXX tbjbxx);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertTBJBXX(TBJBXX... tbjbxx);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertTBJBXX(List<TBJBXX> tbjbxxs);
@Update
void updateTBJBXX(TBJBXX... tbjbxx);
@Update
void updateTBJBXX(List<TBJBXX> tbjbxx);
@Delete
void deleteTBJBXX(TBJBXX... tbjbxx);
@Delete
void deleteTBJBXX(List<TBJBXX> tbjbxx);
}

@ -0,0 +1,87 @@
package cn.org.landcloud.survey.data.bean;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import java.io.Serializable;
@Entity(tableName = "DB_INFO")
public class DBInfo implements Serializable {
/**
* 版本号
* 当前db包的格式规范的版本号当前标准的版本为固定值1.0
*/
@PrimaryKey
@NonNull
private String version;
/**
* 创建时间:
* Db包创建时间格式yyyy-MM-dd HH:mm:ss
*/
private String createtime;
/**
* 修改时间:
* Db包修改时间格式yyyy-MM-dd HH:mm:ss
*/
private String updatetime;
/**
* 生成人员:
* Db包创建人员
*/
private String createuser;
/**
* 描述信息:
* Db包的描述
*/
private String description;
public DBInfo() {
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getCreatetime() {
return createtime;
}
public void setCreatetime(String createtime) {
this.createtime = createtime;
}
public String getUpdatetime() {
return updatetime;
}
public void setUpdatetime(String updatetime) {
this.updatetime = updatetime;
}
public String getCreateuser() {
return createuser;
}
public void setCreateuser(String createuser) {
this.createuser = createuser;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

@ -0,0 +1,89 @@
package cn.org.landcloud.survey.data.bean;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import java.io.Serializable;
/**
* 调查核实信息表
*/
@Entity(tableName = "DCHSXX")
public class DCHSXX implements Serializable {
/**
* 地块标识码:
* 主键地块基本信息表中的地块标识码
*/
@PrimaryKey
@NonNull
private String TBBSM;
/**
* 外业核实情况
*/
private String WYHSQK;
/**
* 扩展信息:
* 扩展信息json字符串根据元数据表进行描述
*/
private String KZXX;
/**
* 调查人员
*/
@NonNull
private String DCRY;
/**
* 调查时间:
* 精确到秒,格式yyyy-MM-dd HH:mm:ss
*/
@NonNull
private String DCSJ;
public DCHSXX() {
}
public String getTBBSM() {
return TBBSM;
}
public void setTBBSM(String TBBSM) {
this.TBBSM = TBBSM;
}
public String getWYHSQK() {
return WYHSQK;
}
public void setWYHSQK(String WYHSQK) {
this.WYHSQK = WYHSQK;
}
public String getKZXX() {
return KZXX;
}
public void setKZXX(String KZXX) {
this.KZXX = KZXX;
}
public String getDCRY() {
return DCRY;
}
public void setDCRY(String DCRY) {
this.DCRY = DCRY;
}
public String getDCSJ() {
return DCSJ;
}
public void setDCSJ(String DCSJ) {
this.DCSJ = DCSJ;
}
}

@ -0,0 +1,395 @@
package cn.org.landcloud.survey.data.bean;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import java.io.Serializable;
/**
* 附件表实体类
*/
@Entity(tableName = "FJ")
public class FJ implements Serializable {
/**
* 标识码,主键
*/
@PrimaryKey
@NonNull
private String BSM;
/**
* 地块类型
*/
@NonNull
private String TBLX;
/**
* 地块标识码:
* 地块基本信息表中的标识码字段
*/
@NonNull
private String TBBSM;
/**
* 县级行政区代码:
* 6位县级行政区代码
*/
@NonNull
private String XZQDM;
/**
* 附件名称:
* 需带格式后缀*.jpg*.png*.mp4等
*/
private String FJMC;
/**
* 附件类型:
* 0手机照片1无人机照片2手机全景3无人机全景4手机视频
* 默认为0
*/
@NonNull
private String FJLX;
/**
* 拍摄特征:
* Y:远景
* J:近景
* T:局部特征
*/
@NonNull
private String PSTZ;
/**
* 附件:
* 文件内容的二进制存储
*/
@NonNull
private byte[] FJ;
/**
* 附件哈希值:
* 附件的哈希值是对文件的内容采用国密SM3计算哈希值
*/
@NonNull
private String FJHXZ;
/**
* 拍摄时间:
* 精确到秒格式yyyy-MM-dd HH:mm:ss
*/
@NonNull
private String PSSJ;
/**
* 拍摄相对高度:
* 单位为米,保留2位小数当为无人机拍摄时高度为无人机的相对高度当为手机拍摄时一般为拍摄人员的身高
*/
@NonNull
private Double XDGD;
/**
* 拍摄绝对高度:
* 拍摄点相对海平面的高度单位为米,保留2位小数当为无人机拍摄时必填
*/
private Double JDGD;
/**
* 拍摄点经度:
* CGCS2000球面坐标保留7位小数
*/
@NonNull
private Double Longitude;
/**
* 拍摄点纬度:
* CGCS2000球面坐标保留7位小数
*/
@NonNull
private Double Latitude;
/**
* 拍摄俯仰角:
* 俯仰角pitch无人机取值一般为[-90,0]手机取值为[-180,180]上翻为正由0至180下翻为负由0至-180无人机一般用相机的角度代替
*/
@NonNull
private Double PSFYJ;
/**
* 拍摄角度:
* 方向角yaw值域范围[0,360]正北为0顺时针方向递增至360
*/
@NonNull
private Double PSJD;
/**
* 拍摄横滚角:
* 横滚角roll值域范围[-180,180],向右滚为正由0至180左滚为负0至-180无人机为0
*/
@NonNull
private Double PSHGJ;
/**
* 拍摄焦距:
* 35mm等效焦距单位mm当附件类型为[0手机照片][1无人机照片]时必填
*/
private Double PSJJ;
/**
* 附件原始宽度:
* 照片压缩前的原始分辨率-当附件类型为[0手机照片][1无人机照片]时必填
*/
private Integer FJYSKD;
/**
* 附件原始高度:
* 照片压缩前的原始分辨率-当附件类型为[0手机照片][1无人机照片]时必填
*/
private Integer FJYSGD;
/**
* 拍摄人员:
* 拍照人员的姓名
*/
@NonNull
private String PSRY;
/**
* 视频扩展信息:
* JSON字符串记录视频拍摄每秒的位置方向等信息当附件类型为[4手机视频]时必填
* [
* {position:时间,x:经度,y:纬度,angel:方位角,height:高度},
* {position:时间,x:经度,y:纬度,angel:方位角,height:高度},
* {position:时间,x:经度,y:纬度,angel:方位角,height:高度}
* ]
* 其中xy经纬度为2000球面坐标系保留7位小数position为视频的时间位置单位秒方位角为度height为高度单位为米保留2位小数angel为方位角为手机的镜头的方向通过yawpitchroll三个值综合计算得出正北为0顺时针旋转到360
* 当附件类型为视频时相关参数为拍摄开始时的参数
*/
private String SPKZXX;
/**
* 证书代码:
* 参考加密信息表证书代码
*/
@NonNull
private String ZSDM;
/**
* 区块链代码:
* 附件信息上链时返回的交易ID
*/
private String QKLDM;
/**
* 校验码:
* 用于校验数据的真伪通过上面的信息
*/
@NonNull
private String JYM;
public FJ() {
}
public String getBSM() {
return BSM;
}
public void setBSM(String BSM) {
this.BSM = BSM;
}
public String getTBLX() {
return TBLX;
}
public void setTBLX(String TBLX) {
this.TBLX = TBLX;
}
public String getTBBSM() {
return TBBSM;
}
public void setTBBSM(String TBBSM) {
this.TBBSM = TBBSM;
}
public String getXZQDM() {
return XZQDM;
}
public void setXZQDM(String XZQDM) {
this.XZQDM = XZQDM;
}
public String getFJMC() {
return FJMC;
}
public void setFJMC(String FJMC) {
this.FJMC = FJMC;
}
public String getFJLX() {
return FJLX;
}
public void setFJLX(String FJLX) {
this.FJLX = FJLX;
}
public String getPSTZ() {
return PSTZ;
}
public void setPSTZ(String PSTZ) {
this.PSTZ = PSTZ;
}
public byte[] getFJ() {
return FJ;
}
public void setFJ(byte[] FJ) {
this.FJ = FJ;
}
public String getFJHXZ() {
return FJHXZ;
}
public void setFJHXZ(String FJHXZ) {
this.FJHXZ = FJHXZ;
}
public String getPSSJ() {
return PSSJ;
}
public void setPSSJ(String PSSJ) {
this.PSSJ = PSSJ;
}
public Double getXDGD() {
return XDGD;
}
public void setXDGD(Double XDGD) {
this.XDGD = XDGD;
}
public Double getJDGD() {
return JDGD;
}
public void setJDGD(Double JDGD) {
this.JDGD = JDGD;
}
public Double getLongitude() {
return Longitude;
}
public void setLongitude(Double longitude) {
Longitude = longitude;
}
public Double getLatitude() {
return Latitude;
}
public void setLatitude(Double latitude) {
Latitude = latitude;
}
public Double getPSFYJ() {
return PSFYJ;
}
public void setPSFYJ(Double PSFYJ) {
this.PSFYJ = PSFYJ;
}
public Double getPSJD() {
return PSJD;
}
public void setPSJD(Double PSJD) {
this.PSJD = PSJD;
}
public Double getPSHGJ() {
return PSHGJ;
}
public void setPSHGJ(Double PSHGJ) {
this.PSHGJ = PSHGJ;
}
public Double getPSJJ() {
return PSJJ;
}
public void setPSJJ(Double PSJJ) {
this.PSJJ = PSJJ;
}
public Integer getFJYSKD() {
return FJYSKD;
}
public void setFJYSKD(Integer FJYSKD) {
this.FJYSKD = FJYSKD;
}
public Integer getFJYSGD() {
return FJYSGD;
}
public void setFJYSGD(Integer FJYSGD) {
this.FJYSGD = FJYSGD;
}
public String getPSRY() {
return PSRY;
}
public void setPSRY(String PSRY) {
this.PSRY = PSRY;
}
public String getSPKZXX() {
return SPKZXX;
}
public void setSPKZXX(String SPKZXX) {
this.SPKZXX = SPKZXX;
}
public String getZSDM() {
return ZSDM;
}
public void setZSDM(String ZSDM) {
this.ZSDM = ZSDM;
}
public String getQKLDM() {
return QKLDM;
}
public void setQKLDM(String QKLDM) {
this.QKLDM = QKLDM;
}
public String getJYM() {
return JYM;
}
public void setJYM(String JYM) {
this.JYM = JYM;
}
}

@ -0,0 +1,91 @@
package cn.org.landcloud.survey.data.bean;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import java.io.Serializable;
@Entity(tableName = "JMXX")
public class JMXX implements Serializable {
/**
* 证书代码:
* 主键在证书颁发时生成
*/
@PrimaryKey
@NonNull
private String ZSDM;
/**
* 数字证书:
* 数字证书文件的内容base64编码的字符串
*/
@NonNull
private String SZZS;
/**
* 证书颁发机构代码:
* 颁发证书机构的统一信用代码
*/
@NonNull
private String ZSBFJGDM;
/**
* 证书颁发机构公钥:
* 颁发证书机构的公开公钥用于验证和解密数字证书
*/
private String ZSBFJGGY;
/**
* 区块链访问地址:
* 区块链访问接口根地址
*/
private String QKLFWDZ;
public JMXX() {
}
@NonNull
public String getZSDM() {
return ZSDM;
}
public void setZSDM(@NonNull String ZSDM) {
this.ZSDM = ZSDM;
}
@NonNull
public String getSZZS() {
return SZZS;
}
public void setSZZS(@NonNull String SZZS) {
this.SZZS = SZZS;
}
@NonNull
public String getZSBFJGDM() {
return ZSBFJGDM;
}
public void setZSBFJGDM(@NonNull String ZSBFJGDM) {
this.ZSBFJGDM = ZSBFJGDM;
}
public String getZSBFJGGY() {
return ZSBFJGGY;
}
public void setZSBFJGGY(String ZSBFJGGY) {
this.ZSBFJGGY = ZSBFJGGY;
}
public String getQKLFWDZ() {
return QKLFWDZ;
}
public void setQKLFWDZ(String QKLFWDZ) {
this.QKLFWDZ = QKLFWDZ;
}
}

@ -0,0 +1,166 @@
package cn.org.landcloud.survey.data.bean;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import java.io.Serializable;
/**
* 扩展信息元数据表
*/
@Entity(tableName = "KZXXYSJ")
public class KZXXYSJ implements Serializable {
/**
* 标识码:
* 主键
*/
@PrimaryKey(autoGenerate = false)
@NonNull
private Integer BSM;
/**
* 地块类型:
* 地块类型例如JCTBSSNYD
*/
@NonNull
private String TBLX;
/**
* 字段名称
*/
@NonNull
private String ZDMC;
/**
* 字段别名,字段的别名一般是中文名称
*/
@NonNull
private String ZDBM;
/**
* 字段描述:
* 字段的中文描述
*/
private String ZDMS;
/**
* 字段类型:
* INTEGER整数TEXT文本REAL数字
*/
@NonNull
private String ZDLX;
/**
* 字段长度
*/
private Integer ZDCD;
/**
* 是否必填:
* 是否必填 YN
*/
@NonNull
private String SFBT;
/**
* 数据字典:
* 当字段类型为DIC时该字段必填
* 具体格式如下[{code:01,description:字典值1的描述},{code:02,description:字典值2的描述},{code:03,description:字典值3的描述}]其中code为字典值description为字典值的描述两者都是文本类型当字典值可多选时对应值用英文逗号拼接例如03,04
*/
private String SJZD;
/**
* 扩展信息类型:
* JBXX基本信息的扩展信息字段
* DCXX调查信息扩展信息字段
*/
@NonNull
private String KZXXLX;
public KZXXYSJ() {
}
public Integer getBSM() {
return BSM;
}
public void setBSM(Integer BSM) {
this.BSM = BSM;
}
public String getTBLX() {
return TBLX;
}
public void setTBLX(String TBLX) {
this.TBLX = TBLX;
}
public String getZDMC() {
return ZDMC;
}
public void setZDMC(String ZDMC) {
this.ZDMC = ZDMC;
}
public String getZDMS() {
return ZDMS;
}
public void setZDMS(String ZDMS) {
this.ZDMS = ZDMS;
}
public String getZDLX() {
return ZDLX;
}
public void setZDLX(String ZDLX) {
this.ZDLX = ZDLX;
}
public Integer getZDCD() {
return ZDCD;
}
public void setZDCD(Integer ZDCD) {
this.ZDCD = ZDCD;
}
public String getSFBT() {
return SFBT;
}
public void setSFBT(String SFBT) {
this.SFBT = SFBT;
}
public String getKZXXLX() {
return KZXXLX;
}
public void setKZXXLX(String KZXXLX) {
this.KZXXLX = KZXXLX;
}
public String getSJZD() {
return SJZD;
}
public void setSJZD(String SJZD) {
this.SJZD = SJZD;
}
public String getZDBM() {
return ZDBM;
}
public void setZDBM(String ZDBM) {
this.ZDBM = ZDBM;
}
}

@ -0,0 +1,192 @@
package cn.org.landcloud.survey.data.bean;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import java.io.Serializable;
/**
* 地块基本信息表
*/
@Entity(tableName = "TBJBXX",indices = {@Index(name = "uidx_tbjbxx_tblx_xzqdm_tbbh", value = {"TBLX","XZQDM","TBBH"} ,unique = true)})
public class TBJBXX implements Serializable {
/**
* 标识码:
* 地块标识码主键全局唯一建议使用GUID
*/
@NonNull
@PrimaryKey
private String BSM;
/**
* 地块类型
*/
@NonNull
private String TBLX;
/**
* 县级行政区代码
*/
@NonNull
private String XZQDM;
/**
* 县级行政区名称
*/
@NonNull
private String XMC;
/**
* 地块编号:
* 区县唯一
*/
@NonNull
private String TBBH;
/**
* 地块名称
*/
private String TBMC;
/**
* 地块面积:
* 单位保留2位小数
*/
@NonNull
private double TBMJ;
/**
* X坐标:
* 投影参考为CGCS2000平面坐标含带号保留3位小数
*/
@NonNull
private double XZB;
/**
* Y坐标:
* 投影参考为CGCS2000平面坐标含带号保留3位小数
*/
@NonNull
private double YZB;
/**
* 备注:
* 选填样本地类编码
*/
private String BZ;
/**
* 扩展信息:
* 扩展信息json字符串根据元数据表进行描述
*/
private String KZXX;
/**
* 地块范围:
* 地块边界标准WKT格式投影参考为CGCS2000平面坐标带带号
*/
@NonNull
private String TBFW;
public TBJBXX() {
}
public String getBSM() {
return BSM;
}
public void setBSM(String BSM) {
this.BSM = BSM;
}
public String getTBLX() {
return TBLX;
}
public void setTBLX(String TBLX) {
this.TBLX = TBLX;
}
public String getXZQDM() {
return XZQDM;
}
public void setXZQDM(String XZQDM) {
this.XZQDM = XZQDM;
}
public String getXMC() {
return XMC;
}
public void setXMC(String XMC) {
this.XMC = XMC;
}
public String getTBBH() {
return TBBH;
}
public void setTBBH(String TBBH) {
this.TBBH = TBBH;
}
public String getTBMC() {
return TBMC;
}
public void setTBMC(String TBMC) {
this.TBMC = TBMC;
}
public double getTBMJ() {
return TBMJ;
}
public void setTBMJ(double TBMJ) {
this.TBMJ = TBMJ;
}
public double getXZB() {
return XZB;
}
public void setXZB(double XZB) {
this.XZB = XZB;
}
public double getYZB() {
return YZB;
}
public void setYZB(double YZB) {
this.YZB = YZB;
}
public String getBZ() {
return BZ;
}
public void setBZ(String BZ) {
this.BZ = BZ;
}
public String getKZXX() {
return KZXX;
}
public void setKZXX(String KZXX) {
this.KZXX = KZXX;
}
public String getTBFW() {
return TBFW;
}
public void setTBFW(String TBFW) {
this.TBFW = TBFW;
}
}

@ -0,0 +1,54 @@
package cn.org.landcloud.survey.util;
import java.io.Closeable;
import java.io.IOException;
/**
* <pre>
* author: Blankj
* blog : http://blankj.com
* time : 2016/10/09
* desc : 关闭相关工具类
* </pre>
*/
public final class CloseUtils {
private CloseUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
/**
* 关闭IO
*
* @param closeables closeables
*/
public static void closeIO(final Closeable... closeables) {
if (closeables == null) return;
for (Closeable closeable : closeables) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 安静关闭IO
*
* @param closeables closeables
*/
public static void closeIOQuietly(final Closeable... closeables) {
if (closeables == null) return;
for (Closeable closeable : closeables) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ignored) {
}
}
}
}
}

@ -0,0 +1,10 @@
package cn.org.landcloud.survey.util;
public class Constants {
public static final String TEST_CER = "eyJjZXJ0Y29kZSI6IjEwMDEiLCJjZXJ0b3JnY29kZSI6IjEyMTAwMDAwNDAwMDEwMzk4UCIsImNlcnRvcmduYW1lIjoi5Lit5Zu95Zu95Zyf5YuY5rWL6KeE5YiS6ZmiIiwiZXhwaXJhdGlvbiI6IjE2OTcyNjkwNTEiLCJzaWduIjoiMzA0NDAyMjAxMkY5MThBRDdBODdEMTQ4MEU4ODZCMzlGOTQ3OTkxQjRFMUExQzBDNUM2MEU3QTVFRTM0M0Y1Rjg2QUE2QjE3MDIyMDM1M0I4Q0ZDQ0QyMjQ0QzM4NDRFMTc5QjM4OEY3ODIwMTBFRjE2RTRBMENFNTU5MDUzM0M3ODA0MjhBNTMyNjEiLCJvcmdjb2RlIjoiOTEzMzAxMTA2Nzk4ODU5NDAxIiwib3JnbmFtZSI6IuadreW3nuS7iuWlpeS/oeaBr+enkeaKgOiCoeS7veaciemZkOWFrOWPuCIsInB1YmxpY2tleSI6IjA0NzgyOEQ1NDY2QUI2QUYyMUZEODUyOEE5MDE2MjJBRTEwMEEzRUQ4MEUyQUZFRkFBMDkzQkVERjM2NjJDNTMyNzMwNURBQTBBODUzNzcwQkEwNjA1RjYyNjZCMDU1MzVFQ0NDNzc0N0JBQTEyMkYxODVDNDdEOUY2NUU3NEU2MEMifQ==";
public static final String TEST_PRIVATEKEY= "00D7D395E6093C63A50A0370D5F6CD89964AB148A846EA96C9969AF08EC1E97513";
public static final String TEST_PUBLICKEY= "047828D5466AB6AF21FD8528A901622AE100A3ED80E2AFEFAA093BEDF3662C5327305DAA0A853770BA0605F6266B05535ECCC7747BAA122F185C47D9F65E74E60C";
public static final String TEST_CERT_ORG_PUBLICKEY= "048D9B68E8DECD33A19A73F87169BB4A65BFE557AA1F58462BAF5D63EFBC5EE5385D1184C3B2A5A0D6EE2ED401182D0E6AF362DCAA8931231399D941AD318D21AD";
public static final String CERT_ORG_CODE = "12100000400010398P";
}

@ -0,0 +1,707 @@
package cn.org.landcloud.survey.util;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
import cn.org.landcloud.survey.util.CloseUtils;
/**
* <pre>
* author: Blankj
* blog : http://blankj.com
* time : 2017/06/22
* desc : 文件读写相关工具类
* </pre>
*/
public final class FileIOUtils {
private FileIOUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
private static final String LINE_SEP = System.getProperty("line.separator");
private static int sBufferSize = 8192;
/**
* 将输入流写入文件
*
* @param filePath 路径
* @param is 输入流
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromIS(final String filePath, final InputStream is) {
return writeFileFromIS(getFileByPath(filePath), is, false);
}
/**
* 将输入流写入文件
*
* @param filePath 路径
* @param is 输入流
* @param append 是否追加在文件末
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromIS(final String filePath, final InputStream is, final boolean append) {
return writeFileFromIS(getFileByPath(filePath), is, append);
}
/**
* 将输入流写入文件
*
* @param file 文件
* @param is 输入流
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromIS(final File file, final InputStream is) {
return writeFileFromIS(file, is, false);
}
/**
* 将输入流写入文件
*
* @param file 文件
* @param is 输入流
* @param append 是否追加在文件末
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromIS(final File file, final InputStream is, final boolean append) {
if (!createOrExistsFile(file) || is == null) return false;
OutputStream os = null;
try {
os = new BufferedOutputStream(new FileOutputStream(file, append));
byte data[] = new byte[sBufferSize];
int len;
while ((len = is.read(data, 0, sBufferSize)) != -1) {
os.write(data, 0, len);
}
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
CloseUtils.closeIO(is, os);
}
}
/**
* 将字节数组写入文件
*
* @param filePath 文件路径
* @param bytes 字节数组
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromBytesByStream(final String filePath, final byte[] bytes) {
return writeFileFromBytesByStream(getFileByPath(filePath), bytes, false);
}
/**
* 将字节数组写入文件
*
* @param filePath 文件路径
* @param bytes 字节数组
* @param append 是否追加在文件末
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromBytesByStream(final String filePath, final byte[] bytes, final boolean append) {
return writeFileFromBytesByStream(getFileByPath(filePath), bytes, append);
}
/**
* 将字节数组写入文件
*
* @param file 文件
* @param bytes 字节数组
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromBytesByStream(final File file, final byte[] bytes) {
return writeFileFromBytesByStream(file, bytes, false);
}
/**
* 将字节数组写入文件
*
* @param file 文件
* @param bytes 字节数组
* @param append 是否追加在文件末
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromBytesByStream(final File file, final byte[] bytes, final boolean append) {
if (bytes == null || !createOrExistsFile(file)) return false;
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream(file, append));
bos.write(bytes);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
CloseUtils.closeIO(bos);
}
}
/**
* 将字节数组写入文件
*
* @param filePath 文件路径
* @param bytes 字节数组
* @param isForce 是否写入文件
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromBytesByChannel(final String filePath, final byte[] bytes, final boolean isForce) {
return writeFileFromBytesByChannel(getFileByPath(filePath), bytes, false, isForce);
}
/**
* 将字节数组写入文件
*
* @param filePath 文件路径
* @param bytes 字节数组
* @param append 是否追加在文件末
* @param isForce 是否写入文件
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromBytesByChannel(final String filePath, final byte[] bytes, final boolean append, final boolean isForce) {
return writeFileFromBytesByChannel(getFileByPath(filePath), bytes, append, isForce);
}
/**
* 将字节数组写入文件
*
* @param file 文件
* @param bytes 字节数组
* @param isForce 是否写入文件
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromBytesByChannel(final File file, final byte[] bytes, final boolean isForce) {
return writeFileFromBytesByChannel(file, bytes, false, isForce);
}
/**
* 将字节数组写入文件
*
* @param file 文件
* @param bytes 字节数组
* @param append 是否追加在文件末
* @param isForce 是否写入文件
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromBytesByChannel(final File file, final byte[] bytes, final boolean append, final boolean isForce) {
if (bytes == null) return false;
FileChannel fc = null;
try {
fc = new FileOutputStream(file, append).getChannel();
fc.position(fc.size());
fc.write(ByteBuffer.wrap(bytes));
if (isForce) fc.force(true);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
CloseUtils.closeIO(fc);
}
}
/**
* 将字节数组写入文件
*
* @param filePath 文件路径
* @param bytes 字节数组
* @param isForce 是否写入文件
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromBytesByMap(final String filePath, final byte[] bytes, final boolean isForce) {
return writeFileFromBytesByMap(filePath, bytes, false, isForce);
}
/**
* 将字节数组写入文件
*
* @param filePath 文件路径
* @param bytes 字节数组
* @param append 是否追加在文件末
* @param isForce 是否写入文件
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromBytesByMap(final String filePath, final byte[] bytes, final boolean append, final boolean isForce) {
return writeFileFromBytesByMap(getFileByPath(filePath), bytes, append, isForce);
}
/**
* 将字节数组写入文件
*
* @param file 文件
* @param bytes 字节数组
* @param isForce 是否写入文件
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromBytesByMap(final File file, final byte[] bytes, final boolean isForce) {
return writeFileFromBytesByMap(file, bytes, false, isForce);
}
/**
* 将字节数组写入文件
*
* @param file 文件
* @param bytes 字节数组
* @param append 是否追加在文件末
* @param isForce 是否写入文件
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromBytesByMap(final File file, final byte[] bytes, final boolean append, final boolean isForce) {
if (bytes == null || !createOrExistsFile(file)) return false;
FileChannel fc = null;
try {
fc = new FileOutputStream(file, append).getChannel();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, fc.size(), bytes.length);
mbb.put(bytes);
if (isForce) mbb.force();
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
CloseUtils.closeIO(fc);
}
}
/**
* 将字符串写入文件
*
* @param filePath 文件路径
* @param content 写入内容
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromString(final String filePath, final String content) {
return writeFileFromString(getFileByPath(filePath), content, false);
}
/**
* 将字符串写入文件
*
* @param filePath 文件路径
* @param content 写入内容
* @param append 是否追加在文件末
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromString(final String filePath, final String content, final boolean append) {
return writeFileFromString(getFileByPath(filePath), content, append);
}
/**
* 将字符串写入文件
*
* @param file 文件
* @param content 写入内容
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromString(final File file, final String content) {
return writeFileFromString(file, content, false);
}
/**
* 将字符串写入文件
*
* @param file 文件
* @param content 写入内容
* @param append 是否追加在文件末
* @return {@code true}: 写入成功<br>{@code false}: 写入失败
*/
public static boolean writeFileFromString(final File file, final String content, final boolean append) {
if (file == null || content == null) return false;
if (!createOrExistsFile(file)) return false;
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(file, append));
bw.write(content);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
CloseUtils.closeIO(bw);
}
}
///////////////////////////////////////////////////////////////////////////
// the divide line of write and read
///////////////////////////////////////////////////////////////////////////
/**
* 读取文件到字符串链表中
*
* @param filePath 文件路径
* @return 字符串链表中
*/
public static List<String> readFile2List(final String filePath) {
return readFile2List(getFileByPath(filePath), null);
}
/**
* 读取文件到字符串链表中
*
* @param filePath 文件路径
* @param charsetName 编码格式
* @return 字符串链表中
*/
public static List<String> readFile2List(final String filePath, final String charsetName) {
return readFile2List(getFileByPath(filePath), charsetName);
}
/**
* 读取文件到字符串链表中
*
* @param file 文件
* @return 字符串链表中
*/
public static List<String> readFile2List(final File file) {
return readFile2List(file, 0, 0x7FFFFFFF, null);
}
/**
* 读取文件到字符串链表中
*
* @param file 文件
* @param charsetName 编码格式
* @return 字符串链表中
*/
public static List<String> readFile2List(final File file, final String charsetName) {
return readFile2List(file, 0, 0x7FFFFFFF, charsetName);
}
/**
* 读取文件到字符串链表中
*
* @param filePath 文件路径
* @param st 需要读取的开始行数
* @param end 需要读取的结束行数
* @return 字符串链表中
*/
public static List<String> readFile2List(final String filePath, final int st, final int end) {
return readFile2List(getFileByPath(filePath), st, end, null);
}
/**
* 读取文件到字符串链表中
*
* @param filePath 文件路径
* @param st 需要读取的开始行数
* @param end 需要读取的结束行数
* @param charsetName 编码格式
* @return 字符串链表中
*/
public static List<String> readFile2List(final String filePath, final int st, final int end, final String charsetName) {
return readFile2List(getFileByPath(filePath), st, end, charsetName);
}
/**
* 读取文件到字符串链表中
*
* @param file 文件
* @param st 需要读取的开始行数
* @param end 需要读取的结束行数
* @return 字符串链表中
*/
public static List<String> readFile2List(final File file, final int st, final int end) {
return readFile2List(file, st, end, null);
}
/**
* 读取文件到字符串链表中
*
* @param file 文件
* @param st 需要读取的开始行数
* @param end 需要读取的结束行数
* @param charsetName 编码格式
* @return 字符串链表中
*/
public static List<String> readFile2List(final File file, final int st, final int end, final String charsetName) {
if (!isFileExists(file)) return null;
if (st > end) return null;
BufferedReader reader = null;
try {
String line;
int curLine = 1;
List<String> list = new ArrayList<>();
if (isSpace(charsetName)) {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
} else {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), charsetName));
}
while ((line = reader.readLine()) != null) {
if (curLine > end) break;
if (st <= curLine && curLine <= end) list.add(line);
++curLine;
}
return list;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
CloseUtils.closeIO(reader);
}
}
/**
* 读取文件到字符串中
*
* @param filePath 文件路径
* @return 字符串
*/
public static String readFile2String(final String filePath) {
return readFile2String(getFileByPath(filePath), null);
}
/**
* 读取文件到字符串中
*
* @param filePath 文件路径
* @param charsetName 编码格式
* @return 字符串
*/
public static String readFile2String(final String filePath, final String charsetName) {
return readFile2String(getFileByPath(filePath), charsetName);
}
/**
* 读取文件到字符串中
*
* @param file 文件
* @return 字符串
*/
public static String readFile2String(final File file) {
return readFile2String(file, null);
}
/**
* 读取文件到字符串中
*
* @param file 文件
* @param charsetName 编码格式
* @return 字符串
*/
public static String readFile2String(final File file, final String charsetName) {
if (!isFileExists(file)) return null;
BufferedReader reader = null;
try {
StringBuilder sb = new StringBuilder();
if (isSpace(charsetName)) {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
} else {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), charsetName));
}
String line;
if ((line = reader.readLine()) != null) {
sb.append(line);
while ((line = reader.readLine()) != null) {
sb.append(LINE_SEP).append(line);
}
}
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
CloseUtils.closeIO(reader);
}
}
/**
* 读取文件到字节数组中
*
* @param filePath 文件路径
* @return 字符数组
*/
public static byte[] readFile2BytesByStream(final String filePath) {
return readFile2BytesByStream(getFileByPath(filePath));
}
/**
* 读取文件到字节数组中
*
* @param file 文件
* @return 字符数组
*/
public static byte[] readFile2BytesByStream(final File file) {
if (!isFileExists(file)) return null;
FileInputStream fis = null;
ByteArrayOutputStream os = null;
try {
fis = new FileInputStream(file);
os = new ByteArrayOutputStream();
byte[] b = new byte[sBufferSize];
int len;
while ((len = fis.read(b, 0, sBufferSize)) != -1) {
os.write(b, 0, len);
}
return os.toByteArray();
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
CloseUtils.closeIO(fis, os);
}
}
/**
* 读取文件到字节数组中
*
* @param filePath 文件路径
* @return 字符数组
*/
public static byte[] readFile2BytesByChannel(final String filePath) {
return readFile2BytesByChannel(getFileByPath(filePath));
}
/**
* 读取文件到字节数组中
*
* @param file 文件
* @return 字符数组
*/
public static byte[] readFile2BytesByChannel(final File file) {
if (!isFileExists(file)) return null;
FileChannel fc = null;
try {
fc = new RandomAccessFile(file, "r").getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate((int) fc.size());
while (true) {
if (!((fc.read(byteBuffer)) > 0)) break;
}
return byteBuffer.array();
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
CloseUtils.closeIO(fc);
}
}
/**
* 读取文件到字节数组中
*
* @param filePath 文件路径
* @return 字符数组
*/
public static byte[] readFile2BytesByMap(final String filePath) {
return readFile2BytesByMap(getFileByPath(filePath));
}
/**
* 读取文件到字节数组中
*
* @param file 文件
* @return 字符数组
*/
public static byte[] readFile2BytesByMap(final File file) {
if (!isFileExists(file)) return null;
FileChannel fc = null;
try {
fc = new RandomAccessFile(file, "r").getChannel();
int size = (int) fc.size();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, size).load();
byte[] result = new byte[size];
mbb.get(result, 0, size);
return result;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
CloseUtils.closeIO(fc);
}
}
/**
* 读取文件指定位置开始的字节数
*
* @param file
* @param readSize
* @param offset
* @return
*/
public static byte[] readFile2Byte(final File file, int readSize, long offset) {
if (!isFileExists(file)) return null;
FileChannel fc = null;
try {
fc = new RandomAccessFile(file, "r").getChannel();
int size = (int) fc.size();
if (offset + readSize > size) return null;
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, offset, readSize).load();
byte[] result = new byte[readSize];
mbb.get(result, 0, readSize);
return result;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
CloseUtils.closeIO(fc);
}
}
/**
* 设置缓冲区尺寸
*
* @param bufferSize 缓冲区大小
*/
public static void setBufferSize(final int bufferSize) {
sBufferSize = bufferSize;
}
private static File getFileByPath(final String filePath) {
return isSpace(filePath) ? null : new File(filePath);
}
private static boolean createOrExistsFile(final String filePath) {
return createOrExistsFile(getFileByPath(filePath));
}
private static boolean createOrExistsFile(final File file) {
if (file == null) return false;
if (file.exists()) return file.isFile();
if (!createOrExistsDir(file.getParentFile())) return false;
try {
return file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
private static boolean createOrExistsDir(final File file) {
return file != null && (file.exists() ? file.isDirectory() : file.mkdirs());
}
private static boolean isFileExists(final File file) {
return file != null && file.exists();
}
private static boolean isSpace(final String s) {
if (s == null) return true;
for (int i = 0, len = s.length(); i < len; ++i) {
if (!Character.isWhitespace(s.charAt(i))) {
return false;
}
}
return true;
}
}

@ -0,0 +1,43 @@
package cn.org.landcloud.survey.util;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* <pre>
* author: Blankj
* blog : http://blankj.com
* time : 2017/03/13
* desc : 时间相关常量
* </pre>
*/
public final class TimeConstants {
/**
* 毫秒与毫秒的倍数
*/
public static final int MSEC = 1;
/**
* 秒与毫秒的倍数
*/
public static final int SEC = 1000;
/**
* 分与毫秒的倍数
*/
public static final int MIN = 60000;
/**
* 时与毫秒的倍数
*/
public static final int HOUR = 3600000;
/**
* 天与毫秒的倍数
*/
public static final int DAY = 86400000;
@IntDef({MSEC, SEC, MIN, HOUR, DAY})
@Retention(RetentionPolicy.SOURCE)
public @interface Unit {
}
}

@ -0,0 +1,31 @@
package cn.org.landcloud.survey.util;
import java.nio.charset.StandardCharsets;
import cn.org.landcloud.security.Util;
import cn.org.landcloud.security.sm2.SM2;
import cn.org.landcloud.security.sm2.SM2EncDecUtils;
import cn.org.landcloud.security.sm2.SM2SignVO;
import cn.org.landcloud.security.sm2.SM2SignVerUtils;
import cn.org.landcloud.security.sm3.SM3Utils;
public class Utils {
/**
* 生成附件校验码
* @param content
* @param privateKey
* @return
*/
public static String makeJYM(String content,String privateKey) {
String hash = SM3Utils.sm3(content);
try {
SM2SignVO sm2SignVO = SM2SignVerUtils.Sign2SM2(Util.hexStringToBytes(privateKey),hash.getBytes(StandardCharsets.UTF_8));
return sm2SignVO.getSm2_signForSoft();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/create_ssl_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="创建公私钥"
android:onClick="createSSL"
tools:ignore="UsingOnClickInXml" />
<Button
android:id="@+id/create_hash_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/create_ssl_btn"
android:text="生成附件hash"
android:onClick="getHash"/>
<Button
android:id="@+id/create_jym_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/create_hash_btn"
android:text="生成附件信息签名"
android:onClick="getJYM"/>
<Button
android:id="@+id/init_data_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/create_jym_btn"
android:text="生成样例成果db包"
android:onClick="initData"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/init_data_btn" >
<TextView
android:id="@+id/log_tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="输出日志"
android:scrollbars="vertical"
android:singleLine="false" />
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Landsurvey" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

@ -0,0 +1,3 @@
<resources>
<string name="app_name">举证数据接口样例</string>
</resources>

@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Landsurvey" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>

@ -0,0 +1,17 @@
package cn.org.landcloud.survey;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

@ -0,0 +1,5 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.3.0' apply false
id 'com.android.library' version '7.3.0' apply false
}

@ -0,0 +1,21 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true

Binary file not shown.

@ -0,0 +1,6 @@
#Wed Oct 12 10:45:05 CST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

185
gradlew vendored

@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
gradlew.bat vendored

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

@ -0,0 +1,17 @@
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "landsurvey"
include ':app'
include ':ssl'

1
ssl/.gitignore vendored

@ -0,0 +1 @@
/build

@ -0,0 +1,21 @@
plugins {
id 'java-library'
}
java {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
/* task makeJar(type: jar) {
delete 'ssl.jar'
from file('src/main/java/')
destinationDir = file('build/libs')
archiveName = 'ssl.jar'
}
makeJar.dependsOn(build)*/
}
dependencies {
implementation 'org.bouncycastle:bcprov-jdk15on:1.63'
compileOnly 'junit:junit:4.13.2'
}

@ -0,0 +1,128 @@
package cn.org.landcloud.security;
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Base64 {
static final char[] charTab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
public Base64() {
}
public static String encode(byte[] data) {
return encode(data, 0, data.length, (StringBuffer) null).toString();
}
public static StringBuffer encode(byte[] data, int start, int len, StringBuffer buf) {
if (null == data || data.length == 0) {
return new StringBuffer();
}
if (buf == null) {
buf = new StringBuffer(data.length * 3 / 2);
}
int end = len - 3;
int i = start;
int n = 0;
int d;
while (i <= end) {
d = (data[i] & 255) << 16 | (data[i + 1] & 255) << 8 | data[i + 2] & 255;
buf.append(charTab[d >> 18 & 63]);
buf.append(charTab[d >> 12 & 63]);
buf.append(charTab[d >> 6 & 63]);
buf.append(charTab[d & 63]);
i += 3;
if (n++ >= 14) {
n = 0;
buf.append("\r\n");
}
}
if (i == start + len - 2) {
d = (data[i] & 255) << 16 | (data[i + 1] & 255) << 8;
buf.append(charTab[d >> 18 & 63]);
buf.append(charTab[d >> 12 & 63]);
buf.append(charTab[d >> 6 & 63]);
buf.append("=");
} else if (i == start + len - 1) {
d = (data[i] & 255) << 16;
buf.append(charTab[d >> 18 & 63]);
buf.append(charTab[d >> 12 & 63]);
buf.append("==");
}
return buf;
}
static int decode(char c) {
if (c >= 65 && c <= 90) {
return c - 65;
} else if (c >= 97 && c <= 122) {
return c - 97 + 26;
} else if (c >= 48 && c <= 57) {
return c - 48 + 26 + 26;
} else {
switch (c) {
case '+':
return 62;
case '/':
return 63;
case '=':
return 0;
default:
throw new RuntimeException("unexpected code: " + c);
}
}
}
public static byte[] decode(String s) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
decode(s, bos);
} catch (IOException var3) {
throw new RuntimeException();
}
return bos.toByteArray();
}
public static void decode(String s, OutputStream os) throws IOException {
int i = 0;
int len = s.length();
while (true) {
while (i < len && s.charAt(i) <= 32) {
++i;
}
if (i == len) {
break;
}
int tri = (decode(s.charAt(i)) << 18) + (decode(s.charAt(i + 1)) << 12) + (decode(s.charAt(i + 2)) << 6) + decode(s.charAt(i + 3));
os.write(tri >> 16 & 255);
if (s.charAt(i + 2) == 61) {
break;
}
os.write(tri >> 8 & 255);
if (s.charAt(i + 3) == 61) {
break;
}
os.write(tri & 255);
i += 4;
}
}
}

@ -0,0 +1,617 @@
package cn.org.landcloud.security;
import java.math.BigInteger;
public class Util {
/**
* 整形转换成网络传输的字节流字节数组型数据
*
* @param num 一个整型数据
* @return 4个字节的自己数组
*/
public static byte[] intToBytes(int num) {
byte[] bytes = new byte[4];
bytes[0] = (byte) (0xff & (num >> 0));
bytes[1] = (byte) (0xff & (num >> 8));
bytes[2] = (byte) (0xff & (num >> 16));
bytes[3] = (byte) (0xff & (num >> 24));
return bytes;
}
/**
* 四个字节的字节数据转换成一个整形数据
*
* @param bytes 4个字节的字节数组
* @return 一个整型数据
*/
public static int byteToInt(byte[] bytes) {
int num = 0;
int temp;
temp = (0x000000ff & (bytes[0])) << 0;
num = num | temp;
temp = (0x000000ff & (bytes[1])) << 8;
num = num | temp;
temp = (0x000000ff & (bytes[2])) << 16;
num = num | temp;
temp = (0x000000ff & (bytes[3])) << 24;
num = num | temp;
return num;
}
/**
* 长整形转换成网络传输的字节流字节数组型数据
*
* @param num 一个长整型数据
* @return 4个字节的自己数组
*/
public static byte[] longToBytes(long num) {
byte[] bytes = new byte[8];
for (int i = 0; i < 8; i++) {
bytes[i] = (byte) (0xff & (num >> (i * 8)));
}
return bytes;
}
/**
* 大数字转换字节流字节数组型数据
*
* @param n
* @return
*/
public static byte[] byteConvert32Bytes(BigInteger n) {
byte tmpd[] = (byte[]) null;
if (n == null) {
return null;
}
if (n.toByteArray().length == 33) {
tmpd = new byte[32];
System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32);
} else if (n.toByteArray().length == 32) {
tmpd = n.toByteArray();
} else {
tmpd = new byte[32];
for (int i = 0; i < 32 - n.toByteArray().length; i++) {
tmpd[i] = 0;
}
System.arraycopy(n.toByteArray(), 0, tmpd, 32 - n.toByteArray().length, n.toByteArray().length);
}
return tmpd;
}
/**
* 换字节流字节数组型数据转大数字
*
* @param b
* @return
*/
public static BigInteger byteConvertInteger(byte[] b) {
if (b[0] < 0) {
byte[] temp = new byte[b.length + 1];
temp[0] = 0;
System.arraycopy(b, 0, temp, 1, b.length);
return new BigInteger(temp);
}
return new BigInteger(b);
}
/**
* 根据字节数组获得值(十六进制数字)
*
* @param bytes
* @return
*/
public static String getHexString(byte[] bytes) {
return getHexString(bytes, true);
}
/**
* 根据字节数组获得值(十六进制数字)
*
* @param bytes
* @param upperCase
* @return
*/
public static String getHexString(byte[] bytes, boolean upperCase) {
String ret = "";
for (int i = 0; i < bytes.length; i++) {
ret += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1);
}
return upperCase ? ret.toUpperCase() : ret;
}
/**
* 打印十六进制字符串
*
* @param bytes
*/
public static void printHexString(byte[] bytes) {
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
System.out.print("0x" + hex.toUpperCase() + ",");
}
System.out.println("");
}
/**
* Convert hex string to byte[]
*
* @param hexString the hex string
* @return byte[]
*/
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
/**
* Convert char to byte
*
* @param c char
* @return byte
*/
public static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
/**
* 用于建立十六进制字符的输出的小写字符数组
*/
private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
/**
* 用于建立十六进制字符的输出的大写字符数组
*/
private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/**
* 将字节数组转换为十六进制字符数组
*
* @param data byte[]
* @return 十六进制char[]
*/
public static char[] encodeHex(byte[] data) {
return encodeHex(data, true);
}
/**
* 将字节数组转换为十六进制字符数组
*
* @param data byte[]
* @param toLowerCase <code>true</code> 传换成小写格式 <code>false</code> 传换成大写格式
* @return 十六进制char[]
*/
public static char[] encodeHex(byte[] data, boolean toLowerCase) {
return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
}
/**
* 将字节数组转换为十六进制字符数组
*
* @param data byte[]
* @param toDigits 用于控制输出的char[]
* @return 十六进制char[]
*/
protected static char[] encodeHex(byte[] data, char[] toDigits) {
int l = data.length;
char[] out = new char[l << 1];
// two characters form the hex value.
for (int i = 0, j = 0; i < l; i++) {
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
out[j++] = toDigits[0x0F & data[i]];
}
return out;
}
/**
* 将字节数组转换为十六进制字符串
*
* @param data byte[]
* @return 十六进制String
*/
public static String encodeHexString(byte[] data) {
return encodeHexString(data, true);
}
/**
* 将字节数组转换为十六进制字符串
*
* @param data byte[]
* @param toLowerCase <code>true</code> 传换成小写格式 <code>false</code> 传换成大写格式
* @return 十六进制String
*/
public static String encodeHexString(byte[] data, boolean toLowerCase) {
return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
}
/**
* 将字节数组转换为十六进制字符串
*
* @param data byte[]
* @param toDigits 用于控制输出的char[]
* @return 十六进制String
*/
protected static String encodeHexString(byte[] data, char[] toDigits) {
return new String(encodeHex(data, toDigits));
}
/**
* 将十六进制字符数组转换为字节数组
*
* @param data 十六进制char[]
* @return byte[]
* @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度将抛出运行时异常
*/
public static byte[] decodeHex(char[] data) {
int len = data.length;
if ((len & 0x01) != 0) {
throw new RuntimeException("Odd number of characters.");
}
byte[] out = new byte[len >> 1];
// two characters form the hex value.
for (int i = 0, j = 0; j < len; i++) {
int f = toDigit(data[j], j) << 4;
j++;
f = f | toDigit(data[j], j);
j++;
out[i] = (byte) (f & 0xFF);
}
return out;
}
/**
* 将十六进制字符转换成一个整数
*
* @param ch 十六进制char
* @param index 十六进制字符在字符数组中的位置
* @return 一个整数
* @throws RuntimeException 当ch不是一个合法的十六进制字符时抛出运行时异常
*/
protected static int toDigit(char ch, int index) {
int digit = Character.digit(ch, 16);
if (digit == -1) {
throw new RuntimeException("Illegal hexadecimal character " + ch
+ " at index " + index);
}
return digit;
}
/**
* 数字字符串转ASCII码字符串
*
* @param String 字符串
* @return ASCII字符串
*/
public static String StringToAsciiString(String content) {
String result = "";
int max = content.length();
for (int i = 0; i < max; i++) {
char c = content.charAt(i);
String b = Integer.toHexString(c);
result = result + b;
}
return result;
}
/**
* 十六进制转字符串
*
* @param hexString 十六进制字符串
* @param encodeType 编码类型4Unicode2普通编码
* @return 字符串
*/
public static String hexStringToString(String hexString, int encodeType) {
String result = "";
int max = hexString.length() / encodeType;
for (int i = 0; i < max; i++) {
char c = (char) hexStringToAlgorism(hexString
.substring(i * encodeType, (i + 1) * encodeType));
result += c;
}
return result;
}
/**
* 十六进制字符串装十进制
*
* @param hex 十六进制字符串
* @return 十进制数值
*/
public static int hexStringToAlgorism(String hex) {
hex = hex.toUpperCase();
int max = hex.length();
int result = 0;
for (int i = max; i > 0; i--) {
char c = hex.charAt(i - 1);
int algorism = 0;
if (c >= '0' && c <= '9') {
algorism = c - '0';
} else {
algorism = c - 55;
}
result += Math.pow(16, max - i) * algorism;
}
return result;
}
/**
* 十六转二进制
*
* @param hex 十六进制字符串
* @return 二进制字符串
*/
public static String hexStringToBinary(String hex) {
hex = hex.toUpperCase();
String result = "";
int max = hex.length();
for (int i = 0; i < max; i++) {
char c = hex.charAt(i);
switch (c) {
case '0':
result += "0000";
break;
case '1':
result += "0001";
break;
case '2':
result += "0010";
break;
case '3':
result += "0011";
break;
case '4':
result += "0100";
break;
case '5':
result += "0101";
break;
case '6':
result += "0110";
break;
case '7':
result += "0111";
break;
case '8':
result += "1000";
break;
case '9':
result += "1001";
break;
case 'A':
result += "1010";
break;
case 'B':
result += "1011";
break;
case 'C':
result += "1100";
break;
case 'D':
result += "1101";
break;
case 'E':
result += "1110";
break;
case 'F':
result += "1111";
break;
}
}
return result;
}
/**
* ASCII码字符串转数字字符串
*
* @param String ASCII字符串
* @return 字符串
*/
public static String AsciiStringToString(String content) {
String result = "";
int length = content.length() / 2;
for (int i = 0; i < length; i++) {
String c = content.substring(i * 2, i * 2 + 2);
int a = hexStringToAlgorism(c);
char b = (char) a;
String d = String.valueOf(b);
result += d;
}
return result;
}
/**
* 将十进制转换为指定长度的十六进制字符串
*
* @param algorism int 十进制数字
* @param maxLength int 转换后的十六进制字符串长度
* @return String 转换后的十六进制字符串
*/
public static String algorismToHexString(int algorism, int maxLength) {
String result = "";
result = Integer.toHexString(algorism);
if (result.length() % 2 == 1) {
result = "0" + result;
}
return patchHexString(result.toUpperCase(), maxLength);
}
/**
* 字节数组转为普通字符串ASCII对应的字符
*
* @param bytearray byte[]
* @return String
*/
public static String byteToString(byte[] bytearray) {
String result = "";
char temp;
int length = bytearray.length;
for (int i = 0; i < length; i++) {
temp = (char) bytearray[i];
result += temp;
}
return result;
}
/**
* 二进制字符串转十进制
*
* @param binary 二进制字符串
* @return 十进制数值
*/
public static int binaryToAlgorism(String binary) {
int max = binary.length();
int result = 0;
for (int i = max; i > 0; i--) {
char c = binary.charAt(i - 1);
int algorism = c - '0';
result += Math.pow(2, max - i) * algorism;
}
return result;
}
/**
* 十进制转换为十六进制字符串
*
* @param algorism int 十进制的数字
* @return String 对应的十六进制字符串
*/
public static String algorismToHEXString(int algorism) {
String result = "";
result = Integer.toHexString(algorism);
if (result.length() % 2 == 1) {
result = "0" + result;
}
result = result.toUpperCase();
return result;
}
/**
* HEX字符串前补0主要用于长度位数不足
*
* @param str String 需要补充长度的十六进制字符串
* @param maxLength int 补充后十六进制字符串的长度
* @return 补充结果
*/
static public String patchHexString(String str, int maxLength) {
String temp = "";
for (int i = 0; i < maxLength - str.length(); i++) {
temp = "0" + temp;
}
str = (temp + str).substring(0, maxLength);
return str;
}
/**
* 将一个字符串转换为int
*
* @param s String 要转换的字符串
* @param defaultInt int 如果出现异常,默认返回的数字
* @param radix int 要转换的字符串是什么进制的,如16 8 10.
* @return int 转换后的数字
*/
public static int parseToInt(String s, int defaultInt, int radix) {
int i = 0;
try {
i = Integer.parseInt(s, radix);
} catch (NumberFormatException ex) {
i = defaultInt;
}
return i;
}
/**
* 将一个十进制形式的数字字符串转换为int
*
* @param s String 要转换的字符串
* @param defaultInt int 如果出现异常,默认返回的数字
* @return int 转换后的数字
*/
public static int parseToInt(String s, int defaultInt) {
int i = 0;
try {
i = Integer.parseInt(s);
} catch (NumberFormatException ex) {
i = defaultInt;
}
return i;
}
/**
* 十六进制串转化为byte数组
*
* @return the array of byte
*/
public static byte[] hexToByte(String hex)
throws IllegalArgumentException {
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException();
}
char[] arr = hex.toCharArray();
byte[] b = new byte[hex.length() / 2];
for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
String swap = "" + arr[i++] + arr[i];
int byteint = Integer.parseInt(swap, 16) & 0xFF;
b[j] = new Integer(byteint).byteValue();
}
return b;
}
/**
* 字节数组转换为十六进制字符串
*
* @param b byte[] 需要转换的字节数组
* @return String 十六进制字符串
*/
public static String byteToHex(byte b[]) {
if (b == null) {
throw new IllegalArgumentException(
"Argument b ( byte array ) is null! ");
}
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
stmp = Integer.toHexString(b[n] & 0xff);
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
}
// return hs.toLowerCase();
return hs.toUpperCase();
}
public static byte[] subByte(byte[] input, int startIndex, int length) {
byte[] bt = new byte[length];
for (int i = 0; i < length; i++) {
bt[i] = input[i + startIndex];
}
return bt;
}
}

@ -0,0 +1,107 @@
package cn.org.landcloud.security.sm2;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
import java.math.BigInteger;
import cn.org.landcloud.security.Util;
public class Cipher {
private int ct;
private ECPoint p2;
private SM3Digest sm3keybase;
private SM3Digest sm3c3;
private byte key[];
private byte keyOff;
public Cipher()
{
this.ct = 1;
this.key = new byte[32];
this.keyOff = 0;
}
private void Reset()
{
this.sm3keybase = new SM3Digest();
this.sm3c3 = new SM3Digest();
byte p[] = Util.byteConvert32Bytes(p2.normalize().getXCoord().toBigInteger());
this.sm3keybase.update(p, 0, p.length);
this.sm3c3.update(p, 0, p.length);
p = Util.byteConvert32Bytes(p2.normalize().getYCoord().toBigInteger());
this.sm3keybase.update(p, 0, p.length);
this.ct = 1;
NextKey();
}
private void NextKey()
{
SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);
sm3keycur.update((byte) (ct >> 24 & 0xff));
sm3keycur.update((byte) (ct >> 16 & 0xff));
sm3keycur.update((byte) (ct >> 8 & 0xff));
sm3keycur.update((byte) (ct & 0xff));
sm3keycur.doFinal(key, 0);
this.keyOff = 0;
this.ct++;
}
public ECPoint Init_enc(SM2 sm2, ECPoint userKey)
{
AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();
ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();
ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
BigInteger k = ecpriv.getD();
ECPoint c1 = ecpub.getQ();
this.p2 = userKey.multiply(k);
Reset();
return c1;
}
public void Encrypt(byte data[])
{
this.sm3c3.update(data, 0, data.length);
for (int i = 0; i < data.length; i++)
{
if (keyOff == key.length)
{
NextKey();
}
data[i] ^= key[keyOff++];
}
}
public void Init_dec(BigInteger userD, ECPoint c1)
{
this.p2 = c1.multiply(userD);
Reset();
}
public void Decrypt(byte data[])
{
for (int i = 0; i < data.length; i++)
{
if (keyOff == key.length)
{
NextKey();
}
data[i] ^= key[keyOff++];
}
this.sm3c3.update(data, 0, data.length);
}
public void Dofinal(byte c3[])
{
byte p[] = Util.byteConvert32Bytes(p2.normalize().getYCoord().toBigInteger());
this.sm3c3.update(p, 0, p.length);
this.sm3c3.doFinal(c3, 0);
Reset();
}
}

@ -0,0 +1,67 @@
package cn.org.landcloud.security.sm2;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECFieldElement.Fp;
import org.bouncycastle.math.ec.ECPoint;
import java.math.BigInteger;
import java.security.SecureRandom;
public class SM2 {
//国密参数
public static String[] ecc_param = {
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"
};
public static SM2 Instance()
{
return new SM2();
}
public final BigInteger ecc_p;
public final BigInteger ecc_a;
public final BigInteger ecc_b;
public final BigInteger ecc_n;
public final BigInteger ecc_gx;
public final BigInteger ecc_gy;
public final ECCurve ecc_curve;
public final ECPoint ecc_point_g;
public final ECDomainParameters ecc_bc_spec;
public final ECKeyPairGenerator ecc_key_pair_generator;
public final ECFieldElement ecc_gx_fieldelement;
public final ECFieldElement ecc_gy_fieldelement;
public SM2()
{
this.ecc_p = new BigInteger(ecc_param[0], 16);
this.ecc_a = new BigInteger(ecc_param[1], 16);
this.ecc_b = new BigInteger(ecc_param[2], 16);
this.ecc_n = new BigInteger(ecc_param[3], 16);
this.ecc_gx = new BigInteger(ecc_param[4], 16);
this.ecc_gy = new BigInteger(ecc_param[5], 16);
this.ecc_gx_fieldelement = new Fp(this.ecc_p, this.ecc_gx);
this.ecc_gy_fieldelement = new Fp(this.ecc_p, this.ecc_gy);
this.ecc_curve = new ECCurve.Fp(this.ecc_p, this.ecc_a, this.ecc_b);
this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement,false);
this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n);
ECKeyGenerationParameters ecc_ecgenparam;
ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());
this.ecc_key_pair_generator = new ECKeyPairGenerator();
this.ecc_key_pair_generator.init(ecc_ecgenparam);
}
}

@ -0,0 +1,208 @@
package cn.org.landcloud.security.sm2;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
import java.io.IOException;
import java.math.BigInteger;
import cn.org.landcloud.security.Util;
public class SM2EncDecUtils {
//生成随机秘钥对
public static SM2KeyVO generateKeyPair(){
SM2 sm2 = SM2.Instance();
AsymmetricCipherKeyPair key = null;
while (true){
key=sm2.ecc_key_pair_generator.generateKeyPair();
if(((ECPrivateKeyParameters) key.getPrivate()).getD().toByteArray().length==32){
break;
}
}
ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();
ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
BigInteger privateKey = ecpriv.getD();
ECPoint publicKey = ecpub.getQ();
SM2KeyVO sm2KeyVO = new SM2KeyVO();
sm2KeyVO.setPublicKey(publicKey);
sm2KeyVO.setPrivateKey(privateKey);
//System.out.println("公钥: " + Util.byteToHex(publicKey.getEncoded()));
//System.out.println("私钥: " + Util.byteToHex(privateKey.toByteArray()));
return sm2KeyVO;
}
//数据加密
public static String encrypt(byte[] publicKey, byte[] data) throws IOException
{
if (publicKey == null || publicKey.length == 0)
{
return null;
}
if (data == null || data.length == 0)
{
return null;
}
byte[] source = new byte[data.length];
System.arraycopy(data, 0, source, 0, data.length);
Cipher cipher = new Cipher();
SM2 sm2 = SM2.Instance();
ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
ECPoint c1 = cipher.Init_enc(sm2, userKey);
cipher.Encrypt(source);
byte[] c3 = new byte[32];
cipher.Dofinal(c3);
// System.out.println("C1 " + Util.byteToHex(c1.getEncoded()));
// System.out.println("C2 " + Util.byteToHex(source));
// System.out.println("C3 " + Util.byteToHex(c3));
//C1 C2 C3拼装成加密字串
// C1 | C2 | C3
//return Util.byteToHex(c1.getEncoded()) + Util.byteToHex(source) + Util.byteToHex(c3);
// C1 | C3 | C2
return Util.byteToHex(c1.getEncoded()) + Util.byteToHex(c3) + Util.byteToHex(source);
}
//数据解密
public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException
{
if (privateKey == null || privateKey.length == 0)
{
return null;
}
if (encryptedData == null || encryptedData.length == 0)
{
return null;
}
//加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2
String data = Util.byteToHex(encryptedData);
/***分解加密字串 C1 | C2 | C3
* C1 = C1标志位2位 + C1实体部分128位 = 130
* C3 = C3实体部分64位 = 64
* C2 = encryptedData.length * 2 - C1长度 - C2长度
byte[] c1Bytes = Util.hexToByte(data.substring(0,130));
int c2Len = encryptedData.length - 97;
byte[] c2 = Util.hexToByte(data.substring(130,130 + 2 * c2Len));
byte[] c3 = Util.hexToByte(data.substring(130 + 2 * c2Len,194 + 2 * c2Len));
*/
/***分解加密字串 C1 | C3 | C2
* C1 = C1标志位2位 + C1实体部分128位 = 130
* C3 = C3实体部分64位 = 64
* C2 = encryptedData.length * 2 - C1长度 - C2长度
*/
byte[] c1Bytes = Util.hexToByte(data.substring(0,130));
int c2Len = encryptedData.length - 97;
byte[] c3 = Util.hexToByte(data.substring(130,130 + 64));
byte[] c2 = Util.hexToByte(data.substring(194,194 + 2 * c2Len));
SM2 sm2 = SM2.Instance();
BigInteger userD = new BigInteger(1, privateKey);
//通过C1实体字节来生成ECPoint
ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);
Cipher cipher = new Cipher();
cipher.Init_dec(userD, c1);
cipher.Decrypt(c2);
cipher.Dofinal(c3);
//返回解密结果
return c2;
}
/* public static BigInteger[] Sm2Sign(byte[] md, AsymmetricCipherKeyPair keypair)
{
SM3Digest sm3 = new SM3Digest();
ECPublicKeyParameters ecpub = (ECPublicKeyParameters)keypair.getPublic();
byte[] z = SM2CryptoServiceProvider.Sm2GetZ(Encoding.Default.GetBytes(SM2CryptoServiceProvider.userId), ecpub.getQ());
sm3.update(z, 0, z.length);
byte[] p = md;
sm3.update(p, 0, p.length);
byte[] hashData = new byte[32];
sm3.doFinal(hashData, 0);
// e
BigInteger e = new BigInteger(1, hashData);
// k
BigInteger k = null;
ECPoint kp = null;
BigInteger r = null;
BigInteger s = null;
BigInteger userD = null;
do
{
do
{
ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)keypair.getPrivate();
k = ecpriv.getD();
kp = ecpub.getQ();
userD = ecpriv.getD();
// r
r = e.add(kp.getX().toBigInteger());
r = r.mod(ecc_n);
}
while (r.equals(BigInteger.ZERO) || r.add(k).equals(ecc_n));
// (1 + dA)~-1
BigInteger da_1 = userD.add(BigInteger.ONE);
da_1 = da_1.modInverse(ecc_n);
// s
s = r.multiply(userD);
s = k.subtract(s).mod(ecc_n);
s = da_1.multiply(s).mod(ecc_n);
}
while (s.equals(BigInteger.ZERO));
byte[] btRS = new byte[64];
byte[] btR = r.toByteArray();
byte[] btS = s.toByteArray();
Array.Copy(btR, btR.length - 32, btRS, 0, 32);
Array.Copy(btS, btS.length - 32, btRS, 32, 32);
return new BigInteger[] { r, s };
}*/
public static void main(String[] args) throws Exception
{
String plainText = "ILoveYou11";
//SM3测试
//生成密钥对
//generateKeyPair();
byte[] sourceData = plainText.getBytes();
//下面的秘钥可以使用generateKeyPair()生成的秘钥内容
// 国密规范正式私钥
//String prik = "3690655E33D5EA3D9A4AE1A1ADD766FDEA045CDEAA43A9206FB8C430CEFE0D94";
// 国密规范正式公钥
//String pubk = "04F6E0C3345AE42B51E06BF50B98834988D54EBC7460FE135A48171BC0629EAE205EEDE253A530608178A98F1E19BB737302813BA39ED3FA3C51639D7A20C7391A";
String prik = "4cf170068e9c47ebdb521fb9fc62c4a55a5773fb9da33b0acf8129e28d09d205";
String pubk = "04aabda53043e8dcb86d42f690b61a4db869821dadf9f851ec3c5c43d0c8f95a6677fdba984afc3bb010a8436b1d17cefc2011a34e01e9e801124d29ffa928d803";
String publicKey ="04BB34D657EE7E8490E66EF577E6B3CEA28B739511E787FB4F71B7F38F241D87F18A5A93DF74E90FF94F4EB907F271A36B295B851F971DA5418F4915E2C1A23D6E";
String privatekey = "0B1CE43098BC21B8E82B5C065EDB534CB86532B1900A49D49F3C53762D2997FA";
prik=privatekey;
pubk=publicKey;
System.out.println("加密: ");
String cipherText = SM2EncDecUtils.encrypt(Util.hexToByte(pubk), sourceData);
//cipherText = "0452ba81cf5119c9f29c81c2be9c4a49ad8c0a33ed899b60548d21a62971a8e994cafc0e9fbc710a0a220b055804bb890833b50ac04ec4e130a5db75338c0c1d49a52a6d373076a5db370564a5cebb5300f79877003c52adf49dac16370e51e14e0754110547bb3b";
System.out.println(cipherText);
System.out.println("解密: ");
plainText = new String(SM2EncDecUtils.decrypt(Util.hexToByte(prik), Util.hexToByte(cipherText)));
System.out.println(plainText);
}
}

@ -0,0 +1,179 @@
package cn.org.landcloud.security.sm2;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECFieldElement.Fp;
import org.bouncycastle.math.ec.ECPoint;
import java.math.BigInteger;
import java.security.SecureRandom;
import cn.org.landcloud.security.Util;
public class SM2Factory {
/*-----------------------国密算法相关参数begin-----------
* ------------------*/
//A 第一系数
private static final BigInteger a = new BigInteger("fffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc",16);
//B 第二系数
private static final BigInteger b = new BigInteger("28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93",16);
//曲线X系数
private static final BigInteger gx = new BigInteger("32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",16);
//曲线Y系数
private static final BigInteger gy = new BigInteger("bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",16);
//生产者顺序系数
private static final BigInteger n = new BigInteger("fffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123",16);
//素数
private static final BigInteger p = new BigInteger("fffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff",16);
//因子系数 1
private static final int h = 1;
/*-----------------------国密算法相关参数end-----------------------------*/
//一些必要类
public final ECFieldElement ecc_gx_fieldelement;
public final ECFieldElement ecc_gy_fieldelement;
public final ECCurve ecc_curve;
public final ECPoint ecc_point_g;
public final ECDomainParameters ecc_bc_spec;
public final ECKeyPairGenerator ecc_key_pair_generator;
/**
* 初始化方法
* @return
*/
public static SM2Factory getInstance(){
return new SM2Factory();
}
public SM2Factory() {
this.ecc_gx_fieldelement = new Fp(this.p,this.gx);
this.ecc_gy_fieldelement = new Fp(this.p, this.gy);
this.ecc_curve = new ECCurve.Fp(this.p, this.a, this.b);
this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement,this.ecc_gy_fieldelement,false);
this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.n);
ECKeyGenerationParameters ecc_ecgenparam;
ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());
this.ecc_key_pair_generator = new ECKeyPairGenerator();
this.ecc_key_pair_generator.init(ecc_ecgenparam);
}
/**
* 根据私钥曲线参数计算Z
* @param userId
* @param userKey
* @return
*/
public byte[] sm2GetZ(byte[] userId, ECPoint userKey){
SM3Digest sm3 = new SM3Digest();
int len = userId.length * 8;
sm3.update((byte) (len >> 8 & 0xFF));
sm3.update((byte) (len & 0xFF));
sm3.update(userId, 0, userId.length);
byte[] p = Util.byteConvert32Bytes(this.a);
sm3.update(p, 0, p.length);
p = Util.byteConvert32Bytes(this.b);
sm3.update(p, 0, p.length);
p = Util.byteConvert32Bytes(this.gx);
sm3.update(p, 0, p.length);
p = Util.byteConvert32Bytes(this.gy);
sm3.update(p, 0, p.length);
p = Util.byteConvert32Bytes(userKey.normalize().getXCoord().toBigInteger());
sm3.update(p, 0, p.length);
p = Util.byteConvert32Bytes(userKey.normalize().getYCoord().toBigInteger());
sm3.update(p, 0, p.length);
byte[] md = new byte[sm3.getDigestSize()];
sm3.doFinal(md, 0);
return md;
}
/**
* 签名相关值计算
* @param md
* @param userD
* @param userKey
* @param sm2Result
*/
public void sm2Sign(byte[] md, BigInteger userD, ECPoint userKey, SM2Result sm2Result) {
BigInteger e = new BigInteger(1, md);
BigInteger k = null;
ECPoint kp = null;
BigInteger r = null;
BigInteger s = null;
do {
do {
// 正式环境
AsymmetricCipherKeyPair keypair = ecc_key_pair_generator.generateKeyPair();
ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) keypair.getPrivate();
ECPublicKeyParameters ecpub = (ECPublicKeyParameters) keypair.getPublic();
k = ecpriv.getD();
kp = ecpub.getQ();
//System.out.println("BigInteger:" + k + "\nECPoint:" + kp);
//System.out.println("计算曲线点X1: "+ kp.getXCoord().toBigInteger().toString(16));
//System.out.println("计算曲线点Y1: "+ kp.getYCoord().toBigInteger().toString(16));
//System.out.println("");
// r
r = e.add(kp.getXCoord().toBigInteger());
r = r.mod(this.n);
} while (r.equals(BigInteger.ZERO) || r.add(k).equals(this.n)||r.toString(16).length()!=64);
// (1 + dA)~-1
BigInteger da_1 = userD.add(BigInteger.ONE);
da_1 = da_1.modInverse(this.n);
// s
s = r.multiply(userD);
s = k.subtract(s).mod(this.n);
s = da_1.multiply(s).mod(this.n);
} while (s.equals(BigInteger.ZERO)||(s.toString(16).length()!=64));
sm2Result.r = r;
sm2Result.s = s;
}
/**
* 验签
* @param md sm3摘要
* @param userKey 根据公钥decode一个ecpoint对象
* @param r 没有特殊含义
* @param s 没有特殊含义
* @param sm2Result 接收参数的对象
*/
public void sm2Verify(byte md[], ECPoint userKey, BigInteger r,
BigInteger s, SM2Result sm2Result) {
sm2Result.R = null;
BigInteger e = new BigInteger(1, md);
BigInteger t = r.add(s).mod(this.n);
if (t.equals(BigInteger.ZERO)) {
return;
} else {
ECPoint x1y1 = ecc_point_g.multiply(sm2Result.s);
//System.out.println("计算曲线点X0: "+ x1y1.normalize().getXCoord().toBigInteger().toString(16));
//System.out.println("计算曲线点Y0: "+ x1y1.normalize().getYCoord().toBigInteger().toString(16));
//System.out.println("");
x1y1 = x1y1.add(userKey.multiply(t));
//System.out.println("计算曲线点X1: "+ x1y1.normalize().getXCoord().toBigInteger().toString(16));
//System.out.println("计算曲线点Y1: "+ x1y1.normalize().getYCoord().toBigInteger().toString(16));
//System.out.println("");
sm2Result.R = e.add(x1y1.normalize().getXCoord().toBigInteger()).mod(this.n);
//System.out.println("R: " + sm2Result.R.toString(16));
return;
}
}
}

@ -0,0 +1,42 @@
package cn.org.landcloud.security.sm2;
import org.bouncycastle.math.ec.ECPoint;
import java.math.BigInteger;
import cn.org.landcloud.security.Util;
public class SM2KeyVO {
BigInteger privateKey ;
ECPoint publicKey ;
public BigInteger getPrivateKey() {
return privateKey;
}
public void setPrivateKey(BigInteger privateKey) {
this.privateKey = privateKey;
}
public ECPoint getPublicKey() {
return publicKey;
}
public void setPublicKey(ECPoint publicKey) {
this.publicKey = publicKey;
}
//HardPubKey:3059301306072A8648CE3D020106082A811CCF5501822D03420004+X+Y
//SoftPubKey:04+X+Y
public String getPubHexInSoft(){
return Util.byteToHex(publicKey.getEncoded());
//System.out.println("公钥: " + );
}
/*public String getPubHexInHard(){
return SecurityTestAll.SM2PubHardKeyHead +Util.byteToHex(publicKey.getEncoded());
}*/
public String getPriHexInSoft(){
return Util.byteToHex(privateKey.toByteArray());
}
}

@ -0,0 +1,28 @@
package cn.org.landcloud.security.sm2;
import org.bouncycastle.math.ec.ECPoint;
import java.math.BigInteger;
/**
* SM2
*/
public class SM2Result {
public SM2Result() {
}
// 签名r
public BigInteger r;
public BigInteger s;
//验签R
public BigInteger R;
// 密钥交换
public byte[] sa;
public byte[] sb;
public byte[] s1;
public byte[] s2;
public ECPoint keyra;
public ECPoint keyrb;
}

@ -0,0 +1,116 @@
package cn.org.landcloud.security.sm2;
/**
* SM2签名所计算的值 可以根据实际情况增加删除字段属性
*/
public class SM2SignVO {
//16进制的私钥
public String sm2_userd;
//椭圆曲线点X
public String x_coord;
//椭圆曲线点Y
public String y_coord;
//SM3摘要Z
public String sm3_z;
//明文数据16进制
public String sign_express;
//SM3摘要值
public String sm3_digest;
//R
public String sign_r;
//S
public String sign_s;
//R
public String verify_r;
//S
public String verify_s;
//签名值
public String sm2_sign;
//sign 签名 verfiy验签
public String sm2_type;
//是否验签成功 true false
public boolean isVerify;
public String getX_coord() {
return x_coord;
}
public void setX_coord(String x_coord) {
this.x_coord = x_coord;
}
public String getY_coord() {
return y_coord;
}
public void setY_coord(String y_coord) {
this.y_coord = y_coord;
}
public String getSm3_z() {
return sm3_z;
}
public void setSm3_z(String sm3_z) {
this.sm3_z = sm3_z;
}
public String getSm3_digest() {
return sm3_digest;
}
public void setSm3_digest(String sm3_digest) {
this.sm3_digest = sm3_digest;
}
public String getSm2_signForSoft() {
return sm2_sign;
}
public String getSm2_signForHard() {
//System.out.println("R:"+getSign_r());
//System.out.println("s:"+getSign_s());
return getSign_r()+getSign_s();
}
public void setSm2_sign(String sm2_sign) {
this.sm2_sign = sm2_sign;
}
public String getSign_express() {
return sign_express;
}
public void setSign_express(String sign_express) {
this.sign_express = sign_express;
}
public String getSm2_userd() {
return sm2_userd;
}
public void setSm2_userd(String sm2_userd) {
this.sm2_userd = sm2_userd;
}
public String getSm2_type() {
return sm2_type;
}
public void setSm2_type(String sm2_type) {
this.sm2_type = sm2_type;
}
public boolean isVerify() {
return isVerify;
}
public void setVerify(boolean isVerify) {
this.isVerify = isVerify;
}
public String getSign_r() {
return sign_r;
}
public void setSign_r(String sign_r) {
this.sign_r = sign_r;
}
public String getSign_s() {
return sign_s;
}
public void setSign_s(String sign_s) {
this.sign_s = sign_s;
}
public String getVerify_r() {
return verify_r;
}
public void setVerify_r(String verify_r) {
this.verify_r = verify_r;
}
public String getVerify_s() {
return verify_s;
}
public void setVerify_s(String verify_s) {
this.verify_s = verify_s;
}
}

@ -0,0 +1,166 @@
package cn.org.landcloud.security.sm2;
import org.bouncycastle.asn1.*;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.math.ec.ECPoint;
import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import cn.org.landcloud.security.Util;
import cn.org.landcloud.security.sm3.SM3Utils;
/**
* 国密算法的签名验签
*/
public class SM2SignVerUtils {
/**
* 默认USERID
*/
public static String USER_ID = "1234567812345678";
/**
* 私钥签名
* 使用SM3进行对明文数据计算一个摘要值
* @param privatekey 私钥
* @param sourceData 明文数据
* @return 签名后的值
* @throws Exception
*/
public static SM2SignVO Sign2SM2(byte[] privatekey,byte[] sourceData) throws Exception{
SM2SignVO sm2SignVO = new SM2SignVO();
sm2SignVO.setSm2_type("sign");
SM2Factory factory = SM2Factory.getInstance();
BigInteger userD = new BigInteger(1,privatekey);
//System.out.println("userD:"+userD.toString(16));
sm2SignVO.setSm2_userd(userD.toString(16));
ECPoint userKey = factory.ecc_point_g.multiply(userD);
//System.out.println("椭圆曲线点X: "+ userKey.getXCoord().toBigInteger().toString(16));
//System.out.println("椭圆曲线点Y: "+ userKey.getYCoord().toBigInteger().toString(16));
SM3Digest sm3Digest = new SM3Digest();
byte [] z = factory.sm2GetZ(USER_ID.getBytes(), userKey);
//System.out.println("SM3摘要Z: " + Util.getHexString(z));
//System.out.println("被加密数据的16进制: " + Util.getHexString(sourceData));
sm2SignVO.setSm3_z(Util.getHexString(z));
sm2SignVO.setSign_express(Util.getHexString(sourceData));
sm3Digest.update(z, 0, z.length);
sm3Digest.update(sourceData,0,sourceData.length);
byte [] md = new byte[32];
sm3Digest.doFinal(md, 0);
//System.out.println("SM3摘要值: " + Util.getHexString(md));
sm2SignVO.setSm3_digest(Util.getHexString(md));
SM2Result sm2Result = new SM2Result();
factory.sm2Sign(md, userD, userKey, sm2Result);
//System.out.println("r: " + sm2Result.r.toString(16));
//System.out.println("s: " + sm2Result.s.toString(16));
// sm2SignVO.setSign_r(sm2Result.r.toString(16));
// sm2SignVO.setSign_s(sm2Result.s.toString(16));
sm2SignVO.setSign_r(Util.byteToHex(sm2Result.r.toByteArray()));
sm2SignVO.setSign_s(Util.byteToHex(sm2Result.s.toByteArray()));
ASN1Integer d_r = new ASN1Integer(sm2Result.r);
ASN1Integer d_s = new ASN1Integer(sm2Result.s);
ASN1EncodableVector v2 = new ASN1EncodableVector();
v2.add(d_r);
v2.add(d_s);
DERSequence sign = new DERSequence(v2);
String result = Util.byteToHex(sign.getEncoded());
sm2SignVO.setSm2_sign(result);
return sm2SignVO;
}
/**
* 验证签名
* @param publicKey 公钥信息
* @param sourceData 密文信息
* @param signData 签名信息
* @return 验签的对象 包含了相关参数和验签结果
*/
@SuppressWarnings("unchecked")
public static SM2SignVO VerifySignSM2(byte[] publicKey,byte[] sourceData,byte[] signData){
try {
byte[] formatedPubKey;
SM2SignVO verifyVo = new SM2SignVO();
verifyVo.setSm2_type("verify");
if (publicKey.length == 64) {
// 添加一字节标识,用于ECPoint解析
formatedPubKey = new byte[65];
formatedPubKey[0] = 0x04;
System.arraycopy(publicKey, 0, formatedPubKey, 1, publicKey.length);
} else{
formatedPubKey = publicKey;
}
SM2Factory factory = SM2Factory.getInstance();
ECPoint userKey = factory.ecc_curve.decodePoint(formatedPubKey);
SM3Digest sm3Digest = new SM3Digest();
byte [] z = factory.sm2GetZ(USER_ID.getBytes(), userKey);
//System.out.println("SM3摘要Z: " + Util.getHexString(z));
verifyVo.setSm3_z(Util.getHexString(z));
sm3Digest.update(z,0,z.length);
sm3Digest.update(sourceData,0,sourceData.length);
byte [] md = new byte[32];
sm3Digest.doFinal(md, 0);
//System.out.println("SM3摘要值: " + Util.getHexString(md));
verifyVo.setSm3_digest(Util.getHexString(md));
ByteArrayInputStream bis = new ByteArrayInputStream(signData);
ASN1InputStream dis = new ASN1InputStream(bis);
SM2Result sm2Result = null;
ASN1Primitive derObj = dis.readObject();
Enumeration<ASN1Integer> e = ((ASN1Sequence)derObj).getObjects();
BigInteger r = ((ASN1Integer) e.nextElement()).getValue();
BigInteger s = ((ASN1Integer) e.nextElement()).getValue();
sm2Result = new SM2Result();
sm2Result.r = r;
sm2Result.s = s;
//System.out.println("vr: " + sm2Result.r.toString(16));
//System.out.println("vs: " + sm2Result.s.toString(16));
// verifyVo.setVerify_r(sm2Result.r.toString(16));
// verifyVo.setVerify_s(sm2Result.s.toString(16));
verifyVo.setVerify_r(Util.byteToHex(sm2Result.r.toByteArray()));
verifyVo.setVerify_s(Util.byteToHex(sm2Result.s.toByteArray()));
factory.sm2Verify(md, userKey, sm2Result.r, sm2Result.s, sm2Result);
boolean verifyFlag = sm2Result.r.equals(sm2Result.R);
verifyVo.setVerify(verifyFlag);
return verifyVo;
} catch (IllegalArgumentException e) {
return null;
}catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) throws Exception {
// String text = "913301106798859401,杭州今奥信息科技股份有限公司,1001,12100000400010398P,中国国土勘测规划院,1697269051,047828D5466AB6AF21FD8528A901622AE100A3ED80E2AFEFAA093BEDF3662C5327305DAA0A853770BA0605F6266B05535ECCC7747BAA122F185C47D9F65E74E60C";
String text = "0D9E4559EAA489079CA46A11BAD09528BDE0E2390226FD825AE1AC10DEA8FFEA,2022-10-18 15:42:56,119.98547,30.277615,41.0,239.0,2.0,test,1001";
// byte [] sourceData = SM3Utils.sm3(text.toString()).getBytes(StandardCharsets.UTF_8);
byte [] sourceData = text.getBytes(StandardCharsets.UTF_8);
//String publicKey ="FA05C51AD1162133DFDF862ECA5E4A481B52FB37FF83E53D45FD18BBD6F32668A92C4692EEB305684E3B9D4ACE767F91D5D108234A9F07936020A92210BA9447";
//String privatekey = "5EB4DF17021CC719B678D970C620690A11B29C8357D71FA4FF9BF7FB6D89767A";
// String publicKey ="04BB34D657EE7E8490E66EF577E6B3CEA28B739511E787FB4F71B7F38F241D87F18A5A93DF74E90FF94F4EB907F271A36B295B851F971DA5418F4915E2C1A23D6E";
// String privatekey = "0B1CE43098BC21B8E82B5C065EDB534CB86532B1900A49D49F3C53762D2997FA";
// String publicKey = "048D9B68E8DECD33A19A73F87169BB4A65BFE557AA1F58462BAF5D63EFBC5EE5385D1184C3B2A5A0D6EE2ED401182D0E6AF362DCAA8931231399D941AD318D21AD";
// String privatekey = "2DD789162386F0E0508D0B4AAE26BE9D7D4075CCBE7536200174FF8D200124B1";
String publicKey = "047828D5466AB6AF21FD8528A901622AE100A3ED80E2AFEFAA093BEDF3662C5327305DAA0A853770BA0605F6266B05535ECCC7747BAA122F185C47D9F65E74E60C";
String privatekey = "00D7D395E6093C63A50A0370D5F6CD89964AB148A846EA96C9969AF08EC1E97513";
// String publicKey ="047828D5466AB6AF21FD8528A901622AE100A3ED80E2AFEFAA093BEDF3662C5327305DAA0A853770BA0605F6266B05535ECCC7747BAA122F185C47D9F65E74E60C";
// String sign = "3046022100A1C51CF002DB42A35AFE36E43E63BDC920397EB101D6A62EC5E016FC4EFFE273022100C3594CBB9D4A5401833F0057F4EC77B41899699C98F5BEF0F079B3BA9D3EB324";
SM2SignVO sign = SM2SignVerUtils.Sign2SM2(Util.hexStringToBytes(privatekey), sourceData);
// SM2SignVO verify = SM2SignVerUtils.VerifySignSM2(Util.hexStringToBytes(publicKey), SM3Utils.sm3(text.toString()).getBytes(StandardCharsets.UTF_8), Util.hexStringToBytes(sign));
SM2SignVO verify = SM2SignVerUtils.VerifySignSM2(Util.hexStringToBytes(publicKey), sourceData, Util.hexStringToBytes(sign.getSm2_signForSoft()));
System.out.println("签名得到的r值:"+sign.getSign_r()+"\n签名值 "+sign.getSm2_signForSoft());
System.out.println("验签得到的R值:"+verify.getVerify_r());
System.err.println("\n验签结果" +verify.isVerify());
}
}

@ -0,0 +1,328 @@
package cn.org.landcloud.security.sm3;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.util.encoders.Hex;
import cn.org.landcloud.security.Util;
/**
* Created by $(USER) on $(DATE)
*/
public class SM3 {
public static final byte[] iv = { 0x73, (byte) 0x80, 0x16, 0x6f, 0x49,
0x14, (byte) 0xb2, (byte) 0xb9, 0x17, 0x24, 0x42, (byte) 0xd7,
(byte) 0xda, (byte) 0x8a, 0x06, 0x00, (byte) 0xa9, 0x6f, 0x30,
(byte) 0xbc, (byte) 0x16, 0x31, 0x38, (byte) 0xaa, (byte) 0xe3,
(byte) 0x8d, (byte) 0xee, 0x4d, (byte) 0xb0, (byte) 0xfb, 0x0e,
0x4e };
public static int[] Tj = new int[64];
static
{
for (int i = 0; i < 16; i++)
{
Tj[i] = 0x79cc4519;
}
for (int i = 16; i < 64; i++)
{
Tj[i] = 0x7a879d8a;
}
}
public static byte[] CF(byte[] V, byte[] B)
{
int[] v, b;
v = convert(V);
b = convert(B);
return convert(CF(v, b));
}
private static int[] convert(byte[] arr)
{
int[] out = new int[arr.length / 4];
byte[] tmp = new byte[4];
for (int i = 0; i < arr.length; i += 4)
{
System.arraycopy(arr, i, tmp, 0, 4);
out[i / 4] = bigEndianByteToInt(tmp);
}
return out;
}
private static byte[] convert(int[] arr)
{
byte[] out = new byte[arr.length * 4];
byte[] tmp = null;
for (int i = 0; i < arr.length; i++)
{
tmp = bigEndianIntToByte(arr[i]);
System.arraycopy(tmp, 0, out, i * 4, 4);
}
return out;
}
public static int[] CF(int[] V, int[] B)
{
int a, b, c, d, e, f, g, h;
int ss1, ss2, tt1, tt2;
a = V[0];
b = V[1];
c = V[2];
d = V[3];
e = V[4];
f = V[5];
g = V[6];
h = V[7];
int[][] arr = expand(B);
int[] w = arr[0];
int[] w1 = arr[1];
for (int j = 0; j < 64; j++)
{
ss1 = (bitCycleLeft(a, 12) + e + bitCycleLeft(Tj[j], j));
ss1 = bitCycleLeft(ss1, 7);
ss2 = ss1 ^ bitCycleLeft(a, 12);
tt1 = FFj(a, b, c, j) + d + ss2 + w1[j];
tt2 = GGj(e, f, g, j) + h + ss1 + w[j];
d = c;
c = bitCycleLeft(b, 9);
b = a;
a = tt1;
h = g;
g = bitCycleLeft(f, 19);
f = e;
e = P0(tt2);
/*System.out.print(j+" ");
System.out.print(Integer.toHexString(a)+" ");
System.out.print(Integer.toHexString(b)+" ");
System.out.print(Integer.toHexString(c)+" ");
System.out.print(Integer.toHexString(d)+" ");
System.out.print(Integer.toHexString(e)+" ");
System.out.print(Integer.toHexString(f)+" ");
System.out.print(Integer.toHexString(g)+" ");
System.out.print(Integer.toHexString(h)+" ");
System.out.println("");*/
}
// System.out.println("");
int[] out = new int[8];
out[0] = a ^ V[0];
out[1] = b ^ V[1];
out[2] = c ^ V[2];
out[3] = d ^ V[3];
out[4] = e ^ V[4];
out[5] = f ^ V[5];
out[6] = g ^ V[6];
out[7] = h ^ V[7];
return out;
}
private static int[][] expand(int[] B)
{
int W[] = new int[68];
int W1[] = new int[64];
for (int i = 0; i < B.length; i++)
{
W[i] = B[i];
}
for (int i = 16; i < 68; i++)
{
W[i] = P1(W[i - 16] ^ W[i - 9] ^ bitCycleLeft(W[i - 3], 15))
^ bitCycleLeft(W[i - 13], 7) ^ W[i - 6];
}
for (int i = 0; i < 64; i++)
{
W1[i] = W[i] ^ W[i + 4];
}
int arr[][] = new int[][] { W, W1 };
return arr;
}
private static byte[] bigEndianIntToByte(int num)
{
return back(Util.intToBytes(num));
}
private static int bigEndianByteToInt(byte[] bytes)
{
return Util.byteToInt(back(bytes));
}
private static int FFj(int X, int Y, int Z, int j)
{
if (j >= 0 && j <= 15)
{
return FF1j(X, Y, Z);
}
else
{
return FF2j(X, Y, Z);
}
}
private static int GGj(int X, int Y, int Z, int j)
{
if (j >= 0 && j <= 15)
{
return GG1j(X, Y, Z);
}
else
{
return GG2j(X, Y, Z);
}
}
// 逻辑位运算函数
private static int FF1j(int X, int Y, int Z)
{
int tmp = X ^ Y ^ Z;
return tmp;
}
private static int FF2j(int X, int Y, int Z)
{
int tmp = ((X & Y) | (X & Z) | (Y & Z));
return tmp;
}
private static int GG1j(int X, int Y, int Z)
{
int tmp = X ^ Y ^ Z;
return tmp;
}
private static int GG2j(int X, int Y, int Z)
{
int tmp = (X & Y) | (~X & Z);
return tmp;
}
private static int P0(int X)
{
int y = rotateLeft(X, 9);
y = bitCycleLeft(X, 9);
int z = rotateLeft(X, 17);
z = bitCycleLeft(X, 17);
int t = X ^ y ^ z;
return t;
}
private static int P1(int X)
{
int t = X ^ bitCycleLeft(X, 15) ^ bitCycleLeft(X, 23);
return t;
}
/**
* 对最后一个分组字节数据padding
*
* @param in
* @param bLen
* 分组个数
* @return
*/
public static byte[] padding(byte[] in, int bLen)
{
int k = 448 - (8 * in.length + 1) % 512;
if (k < 0)
{
k = 960 - (8 * in.length + 1) % 512;
}
k += 1;
byte[] padd = new byte[k / 8];
padd[0] = (byte) 0x80;
long n = in.length * 8 + bLen * 512;
byte[] out = new byte[in.length + k / 8 + 64 / 8];
int pos = 0;
System.arraycopy(in, 0, out, 0, in.length);
pos += in.length;
System.arraycopy(padd, 0, out, pos, padd.length);
pos += padd.length;
byte[] tmp = back(Util.longToBytes(n));
System.arraycopy(tmp, 0, out, pos, tmp.length);
return out;
}
/**
* 字节数组逆序
*
* @param in
* @return
*/
private static byte[] back(byte[] in)
{
byte[] out = new byte[in.length];
for (int i = 0; i < out.length; i++)
{
out[i] = in[out.length - i - 1];
}
return out;
}
public static int rotateLeft(int x, int n)
{
return (x << n) | (x >> (32 - n));
}
private static int bitCycleLeft(int n, int bitLen)
{
bitLen %= 32;
byte[] tmp = bigEndianIntToByte(n);
int byteLen = bitLen / 8;
int len = bitLen % 8;
if (byteLen > 0)
{
tmp = byteCycleLeft(tmp, byteLen);
}
if (len > 0)
{
tmp = bitSmall8CycleLeft(tmp, len);
}
return bigEndianByteToInt(tmp);
}
private static byte[] bitSmall8CycleLeft(byte[] in, int len)
{
byte[] tmp = new byte[in.length];
int t1, t2, t3;
for (int i = 0; i < tmp.length; i++)
{
t1 = (byte) ((in[i] & 0x000000ff) << len);
t2 = (byte) ((in[(i + 1) % tmp.length] & 0x000000ff) >> (8 - len));
t3 = (byte) (t1 | t2);
tmp[i] = (byte) t3;
}
return tmp;
}
private static byte[] byteCycleLeft(byte[] in, int byteLen)
{
byte[] tmp = new byte[in.length];
System.arraycopy(in, byteLen, tmp, 0, in.length - byteLen);
System.arraycopy(in, 0, tmp, in.length - byteLen, byteLen);
return tmp;
}
public static void main(String[] args) {
byte[] md = new byte[32];
byte[] msg1 = "ererfeiisgod".getBytes();
System.out.println(Util.byteToHex(msg1));
SM3Digest sm3 = new SM3Digest();
sm3.update(msg1, 0, msg1.length);
sm3.doFinal(md, 0);
String s = new String(Hex.encode(md));
System.out.println(s.toUpperCase());
}
}

@ -0,0 +1,90 @@
package cn.org.landcloud.security.sm3;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.util.encoders.Hex;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
public class SM3Utils {
/**
* SM3加密生成16进制SM3字符串<br>
*
* @param data 数据
* @return SM3字符串
*/
public static String sm3(byte[] data) {
byte[] md = new byte[32];
SM3Digest sm3 = new SM3Digest();
sm3.update(data, 0, data.length);
sm3.doFinal(md, 0);
String s = new String(Hex.encode(md));
return s.toUpperCase();
}
/**
* SM3加密生成16进制SM3字符串<br>
*
* @param data 数据
* @return SM3字符串
*/
public static String sm3(String data) {
byte[] md = new byte[32];
byte[] msg1 = data.getBytes(StandardCharsets.UTF_8);
//System.out.println(Util.byteToHex(msg1));
SM3Digest sm3 = new SM3Digest();
sm3.update(msg1, 0, msg1.length);
sm3.doFinal(md, 0);
String s = new String(Hex.encode(md));
return s.toUpperCase();
}
/**
* SM3加密生成16进制SM3字符串<br>
*
* @param data 数据
* @return SM3字符串
*/
public static String sm3(InputStream data) throws IOException {
int bufferLength = 8096;
final byte[] buffer = new byte[bufferLength];
int read;
byte[] md = new byte[32];
SM3Digest sm3Digest = new SM3Digest();
while ((read = data.read(buffer, 0, bufferLength)) > -1) {
sm3Digest.update(buffer, 0, read);
}
sm3Digest.doFinal(md, 0);
String s = new String(Hex.encode(md));
return s.toUpperCase();
}
/**
* SM3加密文件生成16进制SM3字符串<br>
*
* @param dataFile 被加密文件
* @return SM3字符串
*/
public static String sm3(File dataFile) throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream(dataFile);
return sm3(fis);
} catch (IOException e) {
e.printStackTrace();
throw new IOException("文件读取异常");
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

@ -0,0 +1,315 @@
package cn.org.landcloud.security.sm4; /**
* Created by $(USER) on $(DATE)
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import cn.org.landcloud.security.Util;
public class SM4 {
public static final int SM4_ENCRYPT = 1;
public static final int SM4_DECRYPT = 0;
private long GET_ULONG_BE(byte[] b, int i) {
long n = (long) (b[i] & 0xff) << 24 | (long) ((b[i + 1] & 0xff) << 16) | (long) ((b[i + 2] & 0xff) << 8) | (long) (b[i + 3] & 0xff) & 0xffffffffL;
return n;
}
private void PUT_ULONG_BE(long n, byte[] b, int i) {
b[i] = (byte) (int) (0xFF & n >> 24);
b[i + 1] = (byte) (int) (0xFF & n >> 16);
b[i + 2] = (byte) (int) (0xFF & n >> 8);
b[i + 3] = (byte) (int) (0xFF & n);
}
private long SHL(long x, int n) {
return (x & 0xFFFFFFFF) << n;
}
private long ROTL(long x, int n) {
return SHL(x, n) | x >> (32 - n);
}
private void SWAP(long[] sk, int i) {
long t = sk[i];
sk[i] = sk[(31 - i)];
sk[(31 - i)] = t;
}
public static final byte[] SboxTable = {(byte) 0xd6, (byte) 0x90, (byte) 0xe9, (byte) 0xfe,
(byte) 0xcc, (byte) 0xe1, 0x3d, (byte) 0xb7, 0x16, (byte) 0xb6,
0x14, (byte) 0xc2, 0x28, (byte) 0xfb, 0x2c, 0x05, 0x2b, 0x67,
(byte) 0x9a, 0x76, 0x2a, (byte) 0xbe, 0x04, (byte) 0xc3,
(byte) 0xaa, 0x44, 0x13, 0x26, 0x49, (byte) 0x86, 0x06,
(byte) 0x99, (byte) 0x9c, 0x42, 0x50, (byte) 0xf4, (byte) 0x91,
(byte) 0xef, (byte) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43,
(byte) 0xed, (byte) 0xcf, (byte) 0xac, 0x62, (byte) 0xe4,
(byte) 0xb3, 0x1c, (byte) 0xa9, (byte) 0xc9, 0x08, (byte) 0xe8,
(byte) 0x95, (byte) 0x80, (byte) 0xdf, (byte) 0x94, (byte) 0xfa,
0x75, (byte) 0x8f, 0x3f, (byte) 0xa6, 0x47, 0x07, (byte) 0xa7,
(byte) 0xfc, (byte) 0xf3, 0x73, 0x17, (byte) 0xba, (byte) 0x83,
0x59, 0x3c, 0x19, (byte) 0xe6, (byte) 0x85, 0x4f, (byte) 0xa8,
0x68, 0x6b, (byte) 0x81, (byte) 0xb2, 0x71, 0x64, (byte) 0xda,
(byte) 0x8b, (byte) 0xf8, (byte) 0xeb, 0x0f, 0x4b, 0x70, 0x56,
(byte) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (byte) 0xd1,
(byte) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (byte) 0x87,
(byte) 0xd4, 0x00, 0x46, 0x57, (byte) 0x9f, (byte) 0xd3, 0x27,
0x52, 0x4c, 0x36, 0x02, (byte) 0xe7, (byte) 0xa0, (byte) 0xc4,
(byte) 0xc8, (byte) 0x9e, (byte) 0xea, (byte) 0xbf, (byte) 0x8a,
(byte) 0xd2, 0x40, (byte) 0xc7, 0x38, (byte) 0xb5, (byte) 0xa3,
(byte) 0xf7, (byte) 0xf2, (byte) 0xce, (byte) 0xf9, 0x61, 0x15,
(byte) 0xa1, (byte) 0xe0, (byte) 0xae, 0x5d, (byte) 0xa4,
(byte) 0x9b, 0x34, 0x1a, 0x55, (byte) 0xad, (byte) 0x93, 0x32,
0x30, (byte) 0xf5, (byte) 0x8c, (byte) 0xb1, (byte) 0xe3, 0x1d,
(byte) 0xf6, (byte) 0xe2, 0x2e, (byte) 0x82, 0x66, (byte) 0xca,
0x60, (byte) 0xc0, 0x29, 0x23, (byte) 0xab, 0x0d, 0x53, 0x4e, 0x6f,
(byte) 0xd5, (byte) 0xdb, 0x37, 0x45, (byte) 0xde, (byte) 0xfd,
(byte) 0x8e, 0x2f, 0x03, (byte) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b,
0x51, (byte) 0x8d, 0x1b, (byte) 0xaf, (byte) 0x92, (byte) 0xbb,
(byte) 0xdd, (byte) 0xbc, 0x7f, 0x11, (byte) 0xd9, 0x5c, 0x41,
0x1f, 0x10, 0x5a, (byte) 0xd8, 0x0a, (byte) 0xc1, 0x31,
(byte) 0x88, (byte) 0xa5, (byte) 0xcd, 0x7b, (byte) 0xbd, 0x2d,
0x74, (byte) 0xd0, 0x12, (byte) 0xb8, (byte) 0xe5, (byte) 0xb4,
(byte) 0xb0, (byte) 0x89, 0x69, (byte) 0x97, 0x4a, 0x0c,
(byte) 0x96, 0x77, 0x7e, 0x65, (byte) 0xb9, (byte) 0xf1, 0x09,
(byte) 0xc5, 0x6e, (byte) 0xc6, (byte) 0x84, 0x18, (byte) 0xf0,
0x7d, (byte) 0xec, 0x3a, (byte) 0xdc, 0x4d, 0x20, 0x79,
(byte) 0xee, 0x5f, 0x3e, (byte) 0xd7, (byte) 0xcb, 0x39, 0x48};
public static final int[] FK = {0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc};
public static final int[] CK = {0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279};
private byte sm4Sbox(byte inch) {
int i = inch & 0xFF;
byte retVal = SboxTable[i];
return retVal;
}
private long sm4Lt(long ka) {
long bb = 0L;
long c = 0L;
byte[] a = new byte[4];
byte[] b = new byte[4];
PUT_ULONG_BE(ka, a, 0);
b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);
bb = GET_ULONG_BE(b, 0);
c = bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24);
return c;
}
private long sm4F(long x0, long x1, long x2, long x3, long rk) {
return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);
}
private long sm4CalciRK(long ka) {
long bb = 0L;
long rk = 0L;
byte[] a = new byte[4];
byte[] b = new byte[4];
PUT_ULONG_BE(ka, a, 0);
b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);
bb = GET_ULONG_BE(b, 0);
rk = bb ^ ROTL(bb, 13) ^ ROTL(bb, 23);
return rk;
}
private void sm4_setkey(long[] SK, byte[] key) {
long[] MK = new long[4];
long[] k = new long[36];
int i = 0;
MK[0] = GET_ULONG_BE(key, 0);
MK[1] = GET_ULONG_BE(key, 4);
MK[2] = GET_ULONG_BE(key, 8);
MK[3] = GET_ULONG_BE(key, 12);
k[0] = MK[0] ^ (long) FK[0];
k[1] = MK[1] ^ (long) FK[1];
k[2] = MK[2] ^ (long) FK[2];
k[3] = MK[3] ^ (long) FK[3];
for (; i < 32; i++) {
k[(i + 4)] = (k[i] ^ sm4CalciRK(k[(i + 1)] ^ k[(i + 2)] ^ k[(i + 3)] ^ (long) CK[i]));
SK[i] = k[(i + 4)];
}
}
private void sm4_one_round(long[] sk, byte[] input, byte[] output) {
int i = 0;
long[] ulbuf = new long[36];
ulbuf[0] = GET_ULONG_BE(input, 0);
ulbuf[1] = GET_ULONG_BE(input, 4);
ulbuf[2] = GET_ULONG_BE(input, 8);
ulbuf[3] = GET_ULONG_BE(input, 12);
while (i < 32) {
ulbuf[(i + 4)] = sm4F(ulbuf[i], ulbuf[(i + 1)], ulbuf[(i + 2)], ulbuf[(i + 3)], sk[i]);
i++;
}
PUT_ULONG_BE(ulbuf[35], output, 0);
PUT_ULONG_BE(ulbuf[34], output, 4);
PUT_ULONG_BE(ulbuf[33], output, 8);
PUT_ULONG_BE(ulbuf[32], output, 12);
}
//修改了填充模式,为模式
private byte[] padding(byte[] input, int mode) {
if (input == null) {
return null;
}
byte[] ret = (byte[]) null;
if (mode == SM4_ENCRYPT) {
//填充:hex必须是32的整数倍填充 ,填充的是80 00 00 00
int p = 16 - input.length % 16;
String inputHex = Util.byteToHex(input)+ "80";
StringBuffer stringBuffer =new StringBuffer(inputHex);
for (int i = 0; i <p-1 ; i++) {
stringBuffer.append("00");
}
ret= Util.hexToByte(stringBuffer.toString());
//ret = new byte[input.length + p];
/*System.arraycopy(input, 0, ret, 0, input.length);
for (int i = 0; i < p; i++) {
ret[input.length + i] = (byte) '<EFBFBD>';
}*/
} else {
/*int p = input[input.length - 1];
ret = new byte[input.length - p];
System.arraycopy(input, 0, ret, 0, input.length - p);*/
String inputHex =Util.byteToHex(input);
int i = inputHex.lastIndexOf("80");
String substring = inputHex.substring(0, i);
ret= Util.hexToByte(substring);
}
return ret;
}
public void sm4_setkey_enc(SM4_Context ctx, byte[] key) throws Exception {
if (ctx == null) {
throw new Exception("ctx is null!");
}
if (key == null || key.length != 16) {
throw new Exception("key error!");
}
ctx.mode = SM4_ENCRYPT;
sm4_setkey(ctx.sk, key);
}
public void sm4_setkey_dec(SM4_Context ctx, byte[] key) throws Exception {
if (ctx == null) {
throw new Exception("ctx is null!");
}
if (key == null || key.length != 16) {
throw new Exception("key error!");
}
int i = 0;
ctx.mode = SM4_DECRYPT;
sm4_setkey(ctx.sk, key);
for (i = 0; i < 16; i++) {
SWAP(ctx.sk, i);
}
}
public byte[] sm4_crypt_ecb(SM4_Context ctx, byte[] input) throws Exception {
if (input == null) {
throw new Exception("input is null!");
}
if ((ctx.isPadding) && (ctx.mode == SM4_ENCRYPT)) {
input = padding(input, SM4_ENCRYPT);
}
int length = input.length;
ByteArrayInputStream bins = new ByteArrayInputStream(input);
ByteArrayOutputStream bous = new ByteArrayOutputStream();
for (; length > 0; length -= 16) {
byte[] in = new byte[16];
byte[] out = new byte[16];
bins.read(in);
sm4_one_round(ctx.sk, in, out);
bous.write(out);
}
byte[] output = bous.toByteArray();
if (ctx.isPadding && ctx.mode == SM4_DECRYPT) {
output = padding(output, SM4_DECRYPT);
}
bins.close();
bous.close();
return output;
}
public byte[] sm4_crypt_cbc(SM4_Context ctx, byte[] iv, byte[] input) throws Exception {
if (iv == null || iv.length != 16) {
throw new Exception("iv error!");
}
if (input == null) {
throw new Exception("input is null!");
}
if (ctx.isPadding && ctx.mode == SM4_ENCRYPT) {
input = padding(input, SM4_ENCRYPT);
}
int i = 0;
int length = input.length;
ByteArrayInputStream bins = new ByteArrayInputStream(input);
ByteArrayOutputStream bous = new ByteArrayOutputStream();
if (ctx.mode == SM4_ENCRYPT) {
for (; length > 0; length -= 16) {
byte[] in = new byte[16];
byte[] out = new byte[16];
byte[] out1 = new byte[16];
bins.read(in);
for (i = 0; i < 16; i++) {
out[i] = ((byte) (in[i] ^ iv[i]));
}
sm4_one_round(ctx.sk, out, out1);
System.arraycopy(out1, 0, iv, 0, 16);
bous.write(out1);
}
} else {
byte[] temp = new byte[16];
for (; length > 0; length -= 16) {
byte[] in = new byte[16];
byte[] out = new byte[16];
byte[] out1 = new byte[16];
bins.read(in);
System.arraycopy(in, 0, temp, 0, 16);
sm4_one_round(ctx.sk, in, out);
for (i = 0; i < 16; i++) {
out1[i] = ((byte) (out[i] ^ iv[i]));
}
System.arraycopy(temp, 0, iv, 0, 16);
bous.write(out1);
}
}
byte[] output = bous.toByteArray();
if (ctx.isPadding && ctx.mode == SM4_DECRYPT) {
output = padding(output, SM4_DECRYPT);
}
bins.close();
bous.close();
return output;
}
}

@ -0,0 +1,173 @@
package cn.org.landcloud.security.sm4; /**
* Created by $(USER) on $(DATE)
*/
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import cn.org.landcloud.security.Base64;
import cn.org.landcloud.security.Util;
public class SM4Utils {
// private String secretKey = "";
// private String iv = "";
// private boolean hexString = false;
public String secretKey = "";
public String iv = "";
public boolean hexString = false;
public SM4Utils() {
}
public String encryptData_ECB(String plainText) {
try {
SM4_Context ctx = new SM4_Context();
ctx.isPadding = true;
ctx.mode = SM4.SM4_ENCRYPT;
byte[] keyBytes;
if (hexString) {
keyBytes = Util.hexStringToBytes(secretKey);
} else {
//keyBytes = secretKey.getBytes();
keyBytes = Util.hexStringToBytes(secretKey);
}
SM4 sm4 = new SM4();
sm4.sm4_setkey_enc(ctx, keyBytes);
byte[] encrypted = sm4.sm4_crypt_ecb(ctx, plainText.getBytes("UTF-8"));
return Util.byteToHex(encrypted);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public String decryptData_ECB(String cipherText) {
try {
byte[] encrypted = Util.hexToByte(cipherText);
cipherText=Base64.encode(encrypted);;
//cipherText = new BASE64Encoder().encode(encrypted);
if (cipherText != null && cipherText.trim().length() > 0) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(cipherText);
cipherText = m.replaceAll("");
}
SM4_Context ctx = new SM4_Context();
ctx.isPadding = true;
ctx.mode = SM4.SM4_DECRYPT;
byte[] keyBytes;
if (hexString) {
keyBytes = Util.hexStringToBytes(secretKey);
} else {
keyBytes = secretKey.getBytes();
}
SM4 sm4 = new SM4();
sm4.sm4_setkey_dec(ctx, keyBytes);
byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Base64.decode(cipherText));
//byte[] decrypted = sm4.sm4_crypt_ecb(ctx, new BASE64Decoder().decodeBuffer(cipherText));
return new String(decrypted, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public String encryptData_CBC(String plainText) {
try {
SM4_Context ctx = new SM4_Context();
ctx.isPadding = true;
ctx.mode = SM4.SM4_ENCRYPT;
byte[] keyBytes;
byte[] ivBytes;
if (hexString) {
keyBytes = Util.hexStringToBytes(secretKey);
ivBytes = Util.hexStringToBytes(iv);
} else {
keyBytes = secretKey.getBytes();
ivBytes = iv.getBytes();
}
SM4 sm4 = new SM4();
sm4.sm4_setkey_enc(ctx, keyBytes);
byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, plainText.getBytes("UTF-8"));
return Util.byteToHex(encrypted);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public String decryptData_CBC(String cipherText) {
try {
byte[] encrypted = Util.hexToByte(cipherText);
cipherText=Base64.encode(encrypted);;
//cipherText = new BASE64Encoder().encode(encrypted);
if (cipherText != null && cipherText.trim().length() > 0) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
Matcher m = p.matcher(cipherText);
cipherText = m.replaceAll("");
}
SM4_Context ctx = new SM4_Context();
ctx.isPadding = true;
ctx.mode = SM4.SM4_DECRYPT;
byte[] keyBytes;
byte[] ivBytes;
if (hexString) {
keyBytes = Util.hexStringToBytes(secretKey);
ivBytes = Util.hexStringToBytes(iv);
} else {
keyBytes = secretKey.getBytes();
ivBytes = iv.getBytes();
}
SM4 sm4 = new SM4();
sm4.sm4_setkey_dec(ctx, keyBytes);
//byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, new BASE64Decoder().decodeBuffer(cipherText));
byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Base64.decode(cipherText));
/*String text = new String(decrypted, "UTF-8");
return text.substring(0,text.length()-1);*/
return new String(decrypted, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) throws IOException {
String plainText = "I Love You Every Day";
String s = Util.byteToHex(plainText.getBytes());
System.out.println("原文" + s);
SM4Utils sm4 = new SM4Utils();
//sm4.secretKey = "JeF8U9wHFOMfs2Y8";
sm4.secretKey = "64EC7C763AB7BF64E2D75FF83A319918";
sm4.hexString = true;
System.out.println("ECB模式加密");
String cipherText = sm4.encryptData_ECB(plainText);
System.out.println("密文: " + cipherText);
System.out.println("");
String plainText2 = sm4.decryptData_ECB(cipherText);
System.out.println("明文: " + plainText2);
System.out.println("");
System.out.println("CBC模式加密");
sm4.iv = "31313131313131313131313131313131";
String cipherText2 = sm4.encryptData_CBC(plainText);
System.out.println("加密密文: " + cipherText2);
System.out.println("");
String plainText3 = sm4.decryptData_CBC(cipherText2);
System.out.println("解密明文: " + plainText3);
}
}

@ -0,0 +1,19 @@
package cn.org.landcloud.security.sm4;
/**
* Created by $(USER) on $(DATE)
*/
public class SM4_Context {
public int mode;
public long[] sk;
public boolean isPadding;
public SM4_Context()
{
this.mode = 1;
this.isPadding = true;
this.sk = new long[32];
}
}

@ -0,0 +1,131 @@
package cn.org.landcloud.security.test;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Test;
import java.io.IOException;
import cn.org.landcloud.security.Util;
import cn.org.landcloud.security.sm2.SM2EncDecUtils;
import cn.org.landcloud.security.sm2.SM2SignVO;
import cn.org.landcloud.security.sm2.SM2SignVerUtils;
public class SecurityTest {
@Test
public void sm2sign() throws Exception {
String src = "0653F3748DFD938FE83935800FF3F526B85C30C2331DD56FCB1794AA99F2A416";
String text = "这是一段明文";
byte[] sourceData = text.getBytes();
//String publicKey ="FA05C51AD1162133DFDF862ECA5E4A481B52FB37FF83E53D45FD18BBD6F32668A92C4692EEB305684E3B9D4ACE767F91D5D108234A9F07936020A92210BA9447";
//String privatekey = "5EB4DF17021CC719B678D970C620690A11B29C8357D71FA4FF9BF7FB6D89767A";
String publicKey = "042780f0963a428a7b030ac1c14a90b967bf365f5394ebf1f0ca1598d4d9bece4fdfa05ba043817fef68bef497088e3992362ce55b1858444fa5a3e00c5042b207";
String privatekey = "73e83d33d95274eeeb23f01834d02fe920b4afece377410435698dfdf1d84203";
SM2SignVO sign = SM2SignVerUtils.Sign2SM2(Util.hexStringToBytes(privatekey), Util.hexToByte(src));
System.out.println("R:"+sign.sign_r);
System.out.println("S:"+sign.sign_s);
//验签硬加密的串
String signYJ = "54720652E5EE53D14F338A03EDAC10E7F93D877EC2168F9287810807D02D2409F3EEE542638AD0B204BC3C8F93EDBCFBE87DEEFB07C0B36F34508AB49B6F90EF";
SM2SignVO verify = SM2SignVerUtils.VerifySignSM2(Util.hexStringToBytes(publicKey), Util.hexToByte(src), Util.hexToByte(SecurityTestAll.SM2SignHardToSoft(signYJ)));
System.err.println("验签结果" + verify.isVerify());
}
@Test
public void sm2sign2() throws Exception {
String src = "32472f598b61ea4ff28f54b00f12ca0a8c1596e2867c5cce4afcb19ee93c2cde";
String text = "这是一段明文";
byte[] sourceData = text.getBytes();
//String publicKey ="FA05C51AD1162133DFDF862ECA5E4A481B52FB37FF83E53D45FD18BBD6F32668A92C4692EEB305684E3B9D4ACE767F91D5D108234A9F07936020A92210BA9447";
//String privatekey = "5EB4DF17021CC719B678D970C620690A11B29C8357D71FA4FF9BF7FB6D89767A";
String publicKey = "0485B52403AEB742F952EFF7200BDBA0A399F0971FEB0EAA0CBE00A1A5EE922A34A24BD9CD2EA740B84290838A862E432BD9BBC0CD0659FD6D172CD1871CD76068";
String privatekey = "62329467E71E70960C7A479C03CA7FC0A2BE92E000240C4F4080F0B2437C536D";
SM2SignVO sign = SM2SignVerUtils.Sign2SM2(Util.hexStringToBytes(privatekey), Util.hexToByte(src));
System.out.println("R:"+sign.sign_r);
System.out.println("S:"+sign.sign_s);
//验签硬加密的串
String signYJ = "233fabe6f81002fbee8c69d9561114d99e0640ecf27d63561d850d77ac76ee5f5d0530bd6eca60e960784f9ad883b77dcfa3c8b274918034faf509faeee2e5ea";
SM2SignVO verify = SM2SignVerUtils.VerifySignSM2(Util.hexStringToBytes(publicKey), Util.hexToByte(src), Util.hexToByte(SecurityTestAll.SM2SignHardToSoft(signYJ)));
System.err.println("验签结果" + verify.isVerify());
}
@Test
public void sm2enc() throws IOException {
String plainText = "ILoveYou11";
//SM3测试
//生成密钥对
//generateKeyPair();
byte[] sourceData = plainText.getBytes();
//下面的秘钥可以使用generateKeyPair()生成的秘钥内容
// 国密规范正式私钥
//String prik = "3690655E33D5EA3D9A4AE1A1ADD766FDEA045CDEAA43A9206FB8C430CEFE0D94";
// 国密规范正式公钥
//String pubk = "04F6E0C3345AE42B51E06BF50B98834988D54EBC7460FE135A48171BC0629EAE205EEDE253A530608178A98F1E19BB737302813BA39ED3FA3C51639D7A20C7391A";
String prik = "4cf170068e9c47ebdb521fb9fc62c4a55a5773fb9da33b0acf8129e28d09d205";
String pubk = "04aabda53043e8dcb86d42f690b61a4db869821dadf9f851ec3c5c43d0c8f95a6677fdba984afc3bb010a8436b1d17cefc2011a34e01e9e801124d29ffa928d803";
String publicKey = "04BB34D657EE7E8490E66EF577E6B3CEA28B739511E787FB4F71B7F38F241D87F18A5A93DF74E90FF94F4EB907F271A36B295B851F971DA5418F4915E2C1A23D6E";
String privatekey = "0B1CE43098BC21B8E82B5C065EDB534CB86532B1900A49D49F3C53762D2997FA";
prik = privatekey;
pubk = publicKey;
System.out.println("加密: ");
String cipherText = SM2EncDecUtils.encrypt(Util.hexToByte(pubk), sourceData);
//cipherText = "0452ba81cf5119c9f29c81c2be9c4a49ad8c0a33ed899b60548d21a62971a8e994cafc0e9fbc710a0a220b055804bb890833b50ac04ec4e130a5db75338c0c1d49a52a6d373076a5db370564a5cebb5300f79877003c52adf49dac16370e51e14e0754110547bb3b";
System.out.println(cipherText);
System.out.println("解密: ");
plainText = new String(SM2EncDecUtils.decrypt(Util.hexToByte(prik), Util.hexToByte(cipherText)));
System.out.println(plainText);
}
@Test
public void sm3() {
byte[] md = new byte[32];
byte[] msg1 = "ererfeiisgod".getBytes();
System.out.println(Util.byteToHex(msg1));
SM3Digest sm3 = new SM3Digest();
sm3.update(msg1, 0, msg1.length);
sm3.doFinal(md, 0);
String s = new String(Hex.encode(md));
System.out.println(s.toUpperCase());
}
@Test
public void sm4() throws IOException {
/*String plainText = "我爱中国啊1我爱我我他2";
String s = Util.byteToHex(plainText.getBytes());
System.out.println("原文" + s);
SM4Utils sm4 = new SM4Utils();
//sm4.secretKey = "JeF8U9wHFOMfs2Y8";
sm4.secretKey = "E76E9B4E0245BC56FCE4E29B208C6A50";
sm4.hexString = true;
System.out.println("ECB模式加密");
String cipherText = sm4.encryptData_ECB(plainText);
System.out.println("密文: " + cipherText);
System.out.println("");
plainText = sm4.decryptData_ECB(cipherText);
System.out.println("明文: " + plainText);
System.out.println("");
System.out.println("CBC模式加密");
sm4.iv = "30303030303030303030303030303030";
cipherText = sm4.encryptData_CBC(plainText);
System.out.println("加密密文: " + cipherText);
System.out.println("");
plainText = sm4.decryptData_CBC(cipherText);
System.out.println("解密明文: " + plainText);*/
}
public static void main(String[] args) throws IOException {
}
}

@ -0,0 +1,219 @@
package cn.org.landcloud.security.test;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.util.encoders.Hex;
import java.io.IOException;
import java.util.UUID;
import cn.org.landcloud.security.Util;
import cn.org.landcloud.security.sm2.SM2EncDecUtils;
import cn.org.landcloud.security.sm2.SM2KeyVO;
import cn.org.landcloud.security.sm2.SM2SignVO;
import cn.org.landcloud.security.sm2.SM2SignVerUtils;
import cn.org.landcloud.security.sm4.SM4Utils;
public class SecurityTestAll {
//SM2公钥编码格式
//HardPubKey:3059301306072A8648CE3D020106082A811CCF5501822D03420004+X+Y
//SoftPubKey:04+X+Y
public static final String SM2PubHardKeyHead = "3059301306072A8648CE3D020106082A811CCF5501822D034200";
//SM2加密 密文区别:软加密多了04
//SM2加密机签名编码格式
//HardSign:R+S
//public static final String SM2PubHardKeyHead="3059301306072A8648CE3D020106082A811CCF5501822D034200";
//private final String SM4_CBC_IV="";
//private final String SM2="";
public static void main(String[] args) throws Exception {
System.out.println("--产生SM2秘钥--:");
SM2KeyVO sm2KeyVO = generateSM2Key();
System.out.println("公钥:" + sm2KeyVO.getPubHexInSoft());
System.out.println("私钥:" + sm2KeyVO.getPriHexInSoft());
//数据加密
System.out.println("--测试加密开始--");
String src = "I Love You";
System.out.println("原文UTF-8转hex:" + Util.byteToHex(src.getBytes()));
String SM2Enc = SM2Enc(sm2KeyVO.getPubHexInSoft(), src);
System.out.println("加密:");
System.out.println("密文:" + SM2Enc);
String SM2Dec = SM2Dec(sm2KeyVO.getPriHexInSoft(), SM2Enc);
System.out.println("解密:" + SM2Dec);
System.out.println("--测试加密结束--");
System.out.println("--测试SM2签名--");
System.out.println("原文hex:" + Util.byteToHex(src.getBytes()));
String s5 = Util.byteToHex(src.getBytes());
System.out.println("签名测试开始:");
SM2SignVO sign = genSM2Signature(sm2KeyVO.getPriHexInSoft(), s5);
System.out.println("软加密签名结果:" + sign.getSm2_signForSoft());
System.out.println("加密机签名结果:" + sign.getSm2_signForHard());
//System.out.println("转签名测试:"+SM2SignHardToSoft(sign.getSm2_signForHard()));
System.out.println("验签1,软件加密方式:");
boolean b = verifySM2Signature(sm2KeyVO.getPubHexInSoft(), s5, sign.getSm2_signForSoft());
System.out.println("软件加密方式验签结果:" + b);
System.out.println("验签2,硬件加密方式:");
String sm2_signForHard = sign.getSm2_signForHard();
System.out.println("签名R:"+sign.sign_r);
System.out.println("签名S:"+sign.sign_s);
//System.out.println("硬:"+sm2_signForHard);
b = verifySM2Signature(sm2KeyVO.getPubHexInSoft(), s5, SM2SignHardToSoft(sign.getSm2_signForHard()));
System.out.println("硬件加密方式验签结果:" + b);
if (!b) {
throw new RuntimeException();
}
System.out.println("--签名测试结束--");
System.out.println("--SM3摘要测试--");
String s = generateSM3HASH(src);
System.out.println("hash:"+s);
System.out.println("--SM3摘要结束--");
System.out.println("--生成SM4秘钥--");
String sm4Key = generateSM4Key();
System.out.println("sm4Key:"+sm4Key);
System.out.println("--生成SM4结束--");
System.out.println("--SM4的CBC加密--");
String s1 = SM4EncForCBC(sm4Key, src);
System.out.println("密文:"+s1);
System.out.println("CBC解密");
String s2 = SM4DecForCBC(sm4Key, s1);
System.out.println("解密结果:"+s2);
System.out.println("--ECB加密--");
String s3 = SM4EncForECB(sm4Key, src);
System.out.println("ECB密文:"+s3);
System.out.println("ECB解密");
String s4 = SM4DecForECB(sm4Key, s3);
System.out.println("ECB解密结果:"+s4);
}
//SM2公钥soft和Hard转换
public static String SM2PubKeySoftToHard(String softKey) {
return SM2PubHardKeyHead + softKey;
}
//SM2公钥Hard和soft转换
public static String SM2PubKeyHardToSoft(String hardKey) {
return hardKey.replaceFirst(SM2PubHardKeyHead, "");
}
//产生非对称秘钥
public static SM2KeyVO generateSM2Key() throws IOException {
SM2KeyVO sm2KeyVO = SM2EncDecUtils.generateKeyPair();
return sm2KeyVO;
}
//公钥加密
public static String SM2Enc(String pubKey, String src) throws IOException {
String encrypt = SM2EncDecUtils.encrypt(Util.hexStringToBytes(pubKey), src.getBytes());
//删除04
encrypt=encrypt.substring(2,encrypt.length());
return encrypt;
}
//私钥解密
public static String SM2Dec(String priKey, String encryptedData) throws IOException {
//填充04
encryptedData="04"+encryptedData;
byte[] decrypt = SM2EncDecUtils.decrypt(Util.hexStringToBytes(priKey), Util.hexStringToBytes(encryptedData));
return new String(decrypt);
}
//私钥签名,参数二:原串必须是hex!!!!因为是直接用于计算签名的,可能是SM3串,也可能是普通串转Hex
public static SM2SignVO genSM2Signature(String priKey, String sourceData) throws Exception {
SM2SignVO sign = SM2SignVerUtils.Sign2SM2(Util.hexToByte(priKey), Util.hexToByte(sourceData));
return sign;
}
//公钥验签,参数二:原串必须是hex!!!!因为是直接用于计算签名的,可能是SM3串,也可能是普通串转Hex
public static boolean verifySM2Signature(String pubKey, String sourceData, String hardSign) {
SM2SignVO verify = SM2SignVerUtils.VerifySignSM2(Util.hexStringToBytes(pubKey), Util.hexToByte(sourceData), Util.hexToByte(hardSign));
return verify.isVerify();
}
//SM2签名Hard转soft
public static String SM2SignHardToSoft(String hardSign) {
byte[] bytes = Util.hexToByte(hardSign);
byte[] r = new byte[bytes.length / 2];
byte[] s = new byte[bytes.length / 2];
System.arraycopy(bytes, 0, r, 0, bytes.length / 2);
System.arraycopy(bytes, bytes.length / 2, s, 0, bytes.length / 2);
ASN1Integer d_r = new ASN1Integer(Util.byteConvertInteger(r));
ASN1Integer d_s = new ASN1Integer(Util.byteConvertInteger(s));
ASN1EncodableVector v2 = new ASN1EncodableVector();
v2.add(d_r);
v2.add(d_s);
DERSequence sign = new DERSequence(v2);
String result = null;
try {
result = Util.byteToHex(sign.getEncoded());
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
//SM2加密机转软加密编码格式
//return SM2SignHardKeyHead+hardSign.substring(0, hardSign.length()/2)+SM2SignHardKeyMid+hardSign.substring(hardSign.length()/2);
return result;
}
//摘要计算
public static String generateSM3HASH(String src) {
byte[] md = new byte[32];
byte[] msg1 = src.getBytes();
//System.out.println(Util.byteToHex(msg1));
SM3Digest sm3 = new SM3Digest();
sm3.update(msg1, 0, msg1.length);
sm3.doFinal(md, 0);
String s = new String(Hex.encode(md));
return s.toUpperCase();
}
//产生对称秘钥
public static String generateSM4Key() {
return UUID.randomUUID().toString().replace("-", "");
}
//对称秘钥加密(CBC)
public static String SM4EncForCBC(String key,String text) {
SM4Utils sm4 = new SM4Utils();
sm4.secretKey = key;
sm4.hexString = true;
sm4.iv = "31313131313131313131313131313131";
String cipherText = sm4.encryptData_CBC(text);
return cipherText;
}
//对称秘钥解密(CBC)
public static String SM4DecForCBC(String key,String text) {
SM4Utils sm4 = new SM4Utils();
sm4.secretKey = key;
sm4.hexString = true;
sm4.iv = "31313131313131313131313131313131";
String plainText = sm4.decryptData_CBC(text);
return plainText;
}
//对称秘钥加密(ECB)
public static String SM4EncForECB(String key,String text) {
SM4Utils sm4 = new SM4Utils();
sm4.secretKey = key;
sm4.hexString = true;
String cipherText = sm4.encryptData_ECB(text);
return cipherText;
}
//对称秘钥解密(ECB)
public static String SM4DecForECB(String key,String text) {
SM4Utils sm4 = new SM4Utils();
sm4.secretKey = key;
sm4.hexString = true;
String plainText = sm4.decryptData_ECB(text);
return plainText;
}
}
Loading…
Cancel
Save