├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ ├── screenshot_20170920_181656.png
│ │ │ │ ├── screenshot_20170920_181704.png
│ │ │ │ └── screenshot_20170920_181748.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── values
│ │ │ │ ├── colors.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── styles.xml
│ │ │ │ └── strings.xml
│ │ │ └── layout
│ │ │ │ ├── activity_regist_success.xml
│ │ │ │ └── activity_regist.xml
│ │ ├── aidl
│ │ │ └── com
│ │ │ │ └── jdnew
│ │ │ │ └── serverapp
│ │ │ │ └── aidl
│ │ │ │ ├── RootLicenseData.aidl
│ │ │ │ └── ILicense.aidl
│ │ ├── java
│ │ │ ├── license
│ │ │ │ └── szca
│ │ │ │ │ └── com
│ │ │ │ │ └── licenseapp
│ │ │ │ │ ├── presenter
│ │ │ │ │ ├── CheckLicensePresenter.java
│ │ │ │ │ ├── RegistPresenter1.java
│ │ │ │ │ └── RegistPresenter.java
│ │ │ │ │ ├── common
│ │ │ │ │ └── Constant.java
│ │ │ │ │ ├── util
│ │ │ │ │ └── EditTextListener.java
│ │ │ │ │ ├── activity
│ │ │ │ │ ├── RegistSuccessActivity.java
│ │ │ │ │ ├── RegistActivity.java
│ │ │ │ │ └── RegistActivity1.java
│ │ │ │ │ ├── view
│ │ │ │ │ ├── IRegistView.java
│ │ │ │ │ └── IRegistView1.java
│ │ │ │ │ └── service
│ │ │ │ │ └── BackService.java
│ │ │ └── com
│ │ │ │ └── jdnew
│ │ │ │ └── serverapp
│ │ │ │ └── aidl
│ │ │ │ └── RootLicenseData.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── license
│ │ │ └── szca
│ │ │ └── com
│ │ │ └── licenseapp
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── license
│ │ └── szca
│ │ └── com
│ │ └── licenseapp
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── serverapp
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── styles.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ └── layout
│ │ │ │ └── activity_main.xml
│ │ ├── aidl
│ │ │ └── com
│ │ │ │ └── jdnew
│ │ │ │ └── serverapp
│ │ │ │ └── aidl
│ │ │ │ ├── RootLicenseData.aidl
│ │ │ │ └── ILicense.aidl
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── jdnew
│ │ │ │ └── serverapp
│ │ │ │ ├── activity
│ │ │ │ └── MainActivity.java
│ │ │ │ ├── aidl
│ │ │ │ └── RootLicenseData.java
│ │ │ │ └── service
│ │ │ │ └── LicenseService.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── jdnew
│ │ │ └── serverapp
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── jdnew
│ │ └── serverapp
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── licensekeylibrary
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ └── values
│ │ │ │ └── strings.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── license
│ │ │ └── szca
│ │ │ └── com
│ │ │ └── licensekeylibrary
│ │ │ ├── CodeUtil.java
│ │ │ ├── SHAUtil.java
│ │ │ ├── RootData.java
│ │ │ ├── RootSubmitData.java
│ │ │ ├── GetDeviceInfoUtil.java
│ │ │ ├── AESUtil.java
│ │ │ ├── GenLicenseKeyUtil.java
│ │ │ └── RSAUtil.java
│ ├── test
│ │ └── java
│ │ │ └── license
│ │ │ └── szca
│ │ │ └── com
│ │ │ └── licensekeylibrary
│ │ │ ├── ExampleUnitTest.java
│ │ │ ├── SHATest.java
│ │ │ ├── LicenseTest.java
│ │ │ ├── RSATest.java
│ │ │ └── AESTest.java
│ └── androidTest
│ │ └── java
│ │ └── license
│ │ └── szca
│ │ └── com
│ │ └── licensekeylibrary
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .idea
├── copyright
│ └── profiles_settings.xml
├── markdown-navigator
│ └── profiles_settings.xml
├── runConfigurations.xml
├── modules.xml
├── compiler.xml
├── gradle.xml
└── misc.xml
├── .gitignore
├── gradle.properties
├── gradlew.bat
├── README.md
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | .idea
--------------------------------------------------------------------------------
/serverapp/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/licensekeylibrary/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | .idea
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':licensekeylibrary', ':serverapp'
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 |
--------------------------------------------------------------------------------
/serverapp/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ServerApp
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/licensekeylibrary/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | LicenseKeyLibrary
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/serverapp/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/serverapp/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/serverapp/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/serverapp/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/.idea/markdown-navigator/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/serverapp/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/serverapp/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/serverapp/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/serverapp/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/serverapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/serverapp/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/serverapp/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/serverapp/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/serverapp/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/serverapp/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/serverapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/serverapp/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/serverapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/serverapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/screenshot_20170920_181656.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-xhdpi/screenshot_20170920_181656.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/screenshot_20170920_181704.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-xhdpi/screenshot_20170920_181704.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/screenshot_20170920_181748.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/app/src/main/res/mipmap-xhdpi/screenshot_20170920_181748.png
--------------------------------------------------------------------------------
/serverapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JDChi/LicenseApp/HEAD/serverapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/aidl/com/jdnew/serverapp/aidl/RootLicenseData.aidl:
--------------------------------------------------------------------------------
1 | // RootLicenseData.aidl
2 | package com.jdnew.serverapp.aidl;
3 |
4 | // Declare any non-default types here with import statements
5 |
6 | parcelable RootLicenseData;
7 |
--------------------------------------------------------------------------------
/serverapp/src/main/aidl/com/jdnew/serverapp/aidl/RootLicenseData.aidl:
--------------------------------------------------------------------------------
1 | // RootLicenseData.aidl
2 | package com.jdnew.serverapp.aidl;
3 |
4 | // Declare any non-default types here with import statements
5 |
6 | parcelable RootLicenseData;
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/serverapp/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/java/license/szca/com/licenseapp/presenter/CheckLicensePresenter.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp.presenter;
2 |
3 | /**
4 | * description
5 | * Created by JD
6 | * on 2017/9/18.
7 | */
8 |
9 | public class CheckLicensePresenter {
10 |
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Sep 12 09:09:10 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/java/license/szca/com/licenseapp/common/Constant.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp.common;
2 |
3 | /**
4 | * description
5 | * Created by JD
6 | * on 2017/9/20.
7 | */
8 |
9 | public class Constant {
10 |
11 | public static final int MSG_GET_LICENSE = 1;
12 | public static final int MSG_CHECK_LICENSE = 2;
13 | }
14 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/aidl/com/jdnew/serverapp/aidl/ILicense.aidl:
--------------------------------------------------------------------------------
1 | // ILicense.aidl
2 | package com.jdnew.serverapp.aidl;
3 |
4 | // Declare any non-default types here with import statements
5 | import com.jdnew.serverapp.aidl.RootLicenseData;
6 |
7 |
8 |
9 |
10 | interface ILicense {
11 |
12 | RootLicenseData returnLicense(String licenseData);
13 |
14 | String returnCheckResult(String submitData);
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/serverapp/src/main/aidl/com/jdnew/serverapp/aidl/ILicense.aidl:
--------------------------------------------------------------------------------
1 | // ILicense.aidl
2 | package com.jdnew.serverapp.aidl;
3 |
4 | // Declare any non-default types here with import statements
5 | import com.jdnew.serverapp.aidl.RootLicenseData;
6 |
7 |
8 |
9 |
10 | interface ILicense {
11 |
12 | RootLicenseData returnLicense(String licenseData);
13 |
14 | String returnCheckResult(String submitData);
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/test/java/license/szca/com/licensekeylibrary/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | /**
4 | * Example local unit test, which will execute on the development machine (host).
5 | *
6 | * @see Testing documentation
7 | */
8 | public class ExampleUnitTest {
9 |
10 |
11 |
12 | public void init(){
13 |
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/serverapp/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/serverapp/src/main/java/com/jdnew/serverapp/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.jdnew.serverapp.activity;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 |
6 | import com.jdnew.serverapp.R;
7 |
8 | public class MainActivity extends AppCompatActivity {
9 |
10 | @Override
11 | protected void onCreate(Bundle savedInstanceState) {
12 | super.onCreate(savedInstanceState);
13 | setContentView(R.layout.activity_main);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/serverapp/src/test/java/com/jdnew/serverapp/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.jdnew.serverapp;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/test/java/license/szca/com/licenseapp/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_regist_success.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/main/java/license/szca/com/licensekeylibrary/CodeUtil.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | import org.spongycastle.util.encoders.Hex;
4 |
5 | /**
6 | * description : 编码工具类
7 | * author : JDNew
8 | * on : 2017/9/17.
9 | */
10 |
11 | public class CodeUtil {
12 |
13 | /**
14 | * 十六进制编码
15 | * @param data
16 | * @return
17 | */
18 | public String hexData(byte[] data) {
19 | // String hexResult = new String(Hex.encode(data));
20 | // return hexResult;
21 | return new String(Hex.encode(data)).toUpperCase();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/java/license/szca/com/licenseapp/util/EditTextListener.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp.util;
2 |
3 | import android.text.Editable;
4 | import android.text.TextWatcher;
5 |
6 | /**
7 | * description
8 | * Created by JD
9 | * on 2017/9/15.
10 | */
11 |
12 | public class EditTextListener implements TextWatcher {
13 | @Override
14 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
15 |
16 | }
17 |
18 | @Override
19 | public void onTextChanged(CharSequence s, int start, int before, int count) {
20 |
21 | }
22 |
23 | @Override
24 | public void afterTextChanged(Editable s) {
25 |
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/license/szca/com/licenseapp/activity/RegistSuccessActivity.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v7.app.AppCompatActivity;
6 |
7 | import license.szca.com.licenseapp.R;
8 |
9 | /**
10 | * description : 注册成功页面
11 | * author : JDNew
12 | * on : 2017/9/17.
13 | */
14 |
15 | public class RegistSuccessActivity extends AppCompatActivity {
16 |
17 | @Override
18 | protected void onCreate(@Nullable Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_regist_success);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/test/java/license/szca/com/licensekeylibrary/SHATest.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 |
6 | import static org.junit.Assert.assertEquals;
7 |
8 | /**
9 | * description
10 | * Created by JD
11 | * on 2017/9/18.
12 | */
13 |
14 | public class SHATest {
15 |
16 | SHAUtil shaUtil;
17 | CodeUtil codeUtil;
18 | String originData = "abc";
19 | @Before
20 | public void init(){
21 | shaUtil = new SHAUtil();
22 | codeUtil = new CodeUtil();
23 | }
24 |
25 | @Test
26 | public void shaTest(){
27 | assertEquals(codeUtil.hexData(shaUtil.encodeSHA1(originData.getBytes())) , codeUtil.hexData(shaUtil.encodeSHA1(originData.getBytes())));
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/app/src/main/java/license/szca/com/licenseapp/view/IRegistView.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp.view;
2 |
3 | /**
4 | * description
5 | * Created by JD
6 | * on 2017/9/12.
7 | */
8 |
9 | public interface IRegistView {
10 | /**
11 | * 获取证书失败
12 | * @param msg
13 | */
14 | void getLicenseKeyFailed(String msg);
15 |
16 | /**
17 | * 获取证书成功
18 | * @param key
19 | */
20 | void getLicenseKeySuccess(String key);
21 |
22 | /**
23 | * 证书校验成功
24 | * @param msg
25 | */
26 | void checkLicenseKeySuccess(String msg);
27 |
28 | /**
29 | * 证书校验失败
30 | * @param msg
31 | */
32 | void checkLicenseKeyFailed(String msg);
33 |
34 | /**
35 | * 加载中
36 | * @param msg
37 | */
38 | void showLoading(String msg);
39 | }
40 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/java/license/szca/com/licenseapp/view/IRegistView1.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp.view;
2 |
3 | /**
4 | * description :
5 | * author : JDNew
6 | * on : 2017/9/24.
7 | */
8 |
9 | public interface IRegistView1 {
10 |
11 | /**
12 | * 获取证书失败
13 | * @param msg
14 | */
15 | void getLicenseKeyFailed(String msg);
16 |
17 | /**
18 | * 获取证书成功
19 | * @param key
20 | */
21 | void getLicenseKeySuccess(String key);
22 |
23 | /**
24 | * 证书校验成功
25 | * @param msg
26 | */
27 | void checkLicenseKeySuccess(String msg);
28 |
29 | /**
30 | * 证书校验失败
31 | * @param msg
32 | */
33 | void checkLicenseKeyFailed(String msg);
34 |
35 | /**
36 | * 加载中
37 | * @param msg
38 | */
39 | void showLoading(String msg);
40 | }
41 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/test/java/license/szca/com/licensekeylibrary/LicenseTest.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 |
6 | import org.junit.Before;
7 | import org.junit.Test;
8 |
9 | /**
10 | * description 生成的20位license的测试类
11 | * Created by JD
12 | * on 2017/9/14.
13 | */
14 |
15 | public class LicenseTest {
16 |
17 | private String testData = "hello";
18 | private Context mContext;
19 | private GenLicenseKeyUtil genLicenseKeyUtil;
20 |
21 | @Before
22 | public void init(){
23 |
24 |
25 | mContext = InstrumentationRegistry.getContext();
26 | genLicenseKeyUtil = new GenLicenseKeyUtil(mContext);
27 | }
28 |
29 | @Test
30 | public void shaTest(){
31 |
32 | }
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | LicenseApp
3 |
4 |
5 | Email
6 | Password (optional)
7 | Sign in or register
8 | Sign in
9 | This email address is invalid
10 | This password is too short
11 | This password is incorrect
12 | This field is required
13 | "Contacts permissions are needed for providing email
14 | completions."
15 |
16 |
17 |
--------------------------------------------------------------------------------
/serverapp/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/serverapp/src/androidTest/java/com/jdnew/serverapp/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.jdnew.serverapp;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.jdnew.serverapp", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/license/szca/com/licenseapp/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("license.szca.com.licenseapp", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/androidTest/java/license/szca/com/licensekeylibrary/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("license.szca.com.licensekeylibrary.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/test/java/license/szca/com/licensekeylibrary/RSATest.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 |
6 | import static org.junit.Assert.assertEquals;
7 |
8 | /**
9 | * description : RSA测试类
10 | * author : JDNew
11 | * on : 2017/9/17.
12 | */
13 |
14 | public class RSATest {
15 |
16 |
17 | private RSAUtil rsaUtil;
18 | private String originData = "abc";
19 |
20 | @Before
21 | public void init() {
22 | rsaUtil = new RSAUtil();
23 | //初始化生成公钥和密钥
24 | rsaUtil.initPrivateAndPublicKey();
25 | }
26 |
27 | @Test
28 | public void rsaTest() {
29 | //私钥加密
30 | byte[] encryptData = rsaUtil.encryptWithPrivateKey(originData.getBytes(), rsaUtil.getPrivateKey());
31 | //公钥解密
32 | byte[] decryptData = rsaUtil.decryptWithPublicKey(encryptData, rsaUtil.getPublicKey());
33 |
34 | assertEquals(originData, new String(decryptData));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\edao\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/serverapp/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in E:\installation\Android\Android\androidsdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/licensekeylibrary/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\edao\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/serverapp/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 26
5 | buildToolsVersion "26.0.1"
6 |
7 | defaultConfig {
8 | applicationId "com.jdnew.serverapp"
9 | minSdkVersion 21
10 | targetSdkVersion 26
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
15 |
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | compile fileTree(include: ['*.jar'], dir: 'libs')
27 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
28 | exclude group: 'com.android.support', module: 'support-annotations'
29 | })
30 | compile 'com.android.support:appcompat-v7:26.+'
31 | compile 'com.android.support.constraint:constraint-layout:1.0.2'
32 | testCompile 'junit:junit:4.12'
33 | compile project(':licensekeylibrary')
34 | }
35 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | signingConfigs {
5 |
6 | }
7 | compileSdkVersion 25
8 | buildToolsVersion "25.0.0"
9 | defaultConfig {
10 | applicationId "license.szca.com.licenseapp"
11 | minSdkVersion 14
12 | targetSdkVersion 25
13 | versionCode 1
14 | versionName "1.0"
15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | compile fileTree(include: ['*.jar'], dir: 'libs')
27 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
28 | exclude group: 'com.android.support', module: 'support-annotations'
29 | })
30 | compile 'com.android.support:appcompat-v7:25.+'
31 | compile 'com.android.support:design:25.+'
32 | testCompile 'junit:junit:4.12'
33 | compile project(':licensekeylibrary')
34 | }
35 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/main/java/license/szca/com/licensekeylibrary/SHAUtil.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | import java.security.MessageDigest;
4 | import java.security.NoSuchAlgorithmException;
5 | import java.security.Security;
6 |
7 | /**
8 | * description : SHA消息摘要工具类
9 | * author : JDNew
10 | * on : 2017/9/17.
11 | */
12 |
13 | public class SHAUtil {
14 | static {
15 | //从位置1开始,添加新的提供者
16 | Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
17 | }
18 | /**
19 | * 使用SHA1进行消息摘要
20 | *
21 | * @param data
22 | * @return
23 | */
24 | public byte[] encodeSHA1(byte[] data) {
25 | byte[] dataByte = null;
26 | byte[] newDataByte = null;
27 | try {
28 | MessageDigest messageDigest = MessageDigest.getInstance("SHA");
29 | dataByte = messageDigest.digest(data);
30 | //摘要后截取后10位返回
31 | newDataByte = new byte[10];
32 | System.arraycopy(dataByte, 9, newDataByte, 0, 10);
33 | } catch (NoSuchAlgorithmException e) {
34 | e.printStackTrace();
35 | }
36 |
37 | return newDataByte;
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/serverapp/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/licensekeylibrary/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.0"
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 |
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | compile fileTree(include: ['*.jar'], dir: 'libs')
26 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
27 | exclude group: 'com.android.support', module: 'support-annotations'
28 | })
29 | compile 'com.android.support:appcompat-v7:25.+'
30 | testCompile 'junit:junit:4.12'
31 | compile 'com.madgag.spongycastle:core:1.58.0.0'
32 | compile 'com.madgag.spongycastle:prov:1.58.0.0'
33 | compile 'com.madgag.spongycastle:pkix:1.54.0.0'
34 | compile 'com.madgag.spongycastle:pg:1.54.0.0'
35 | compile 'com.android.support.test:runner:0.5'
36 | compile 'com.google.code.gson:gson:2.8.1'
37 | }
38 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/main/java/license/szca/com/licensekeylibrary/RootData.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | /**
4 | * description : 客户端数据的实体类
5 | * author : JDNew
6 | * on : 2017/9/17.
7 | */
8 |
9 | public class RootData {
10 | private String userName;
11 | private String uuid;
12 | private String applicationId;
13 | private String licenseKey;
14 | private String appSignture;
15 |
16 |
17 |
18 |
19 | public void setUuid(String uuid) {
20 | this.uuid = uuid;
21 | }
22 |
23 | public String getUuid() {
24 | return uuid;
25 | }
26 |
27 | public void setApplicationId(String applicationId) {
28 | this.applicationId = applicationId;
29 | }
30 |
31 | public String getApplicationId() {
32 | return applicationId;
33 | }
34 |
35 | public void setUserName(String userName) {
36 | this.userName = userName;
37 | }
38 |
39 | public String getUserName() {
40 | return userName;
41 | }
42 |
43 | public String getAppSignture() {
44 | return appSignture;
45 | }
46 |
47 | public void setAppSignture(String appSignture) {
48 | this.appSignture = appSignture;
49 | }
50 |
51 | public String getLicenseKey() {
52 | return licenseKey;
53 | }
54 |
55 | public void setLicenseKey(String licenseKey) {
56 | this.licenseKey = licenseKey;
57 | }
58 |
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/main/java/license/szca/com/licensekeylibrary/RootSubmitData.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | /**
4 | * description 提交给客户端的数据实体类
5 | * Created by JD
6 | * on 2017/9/18.
7 | */
8 |
9 | public class RootSubmitData {
10 |
11 | /**
12 | * AES密钥,用于解密出客户端数据
13 | */
14 | private String encrptAESKey;
15 | /**
16 | * 被AES加密过的数据
17 | */
18 | private String encryptAESClientData;
19 | /**
20 | * 签名后的数据
21 | */
22 | private String signData;
23 | /**
24 | * RSA签名公钥
25 | */
26 | private String rsaSignPublicKey;
27 |
28 |
29 |
30 | public String getEncrptAESKey() {
31 | return encrptAESKey;
32 | }
33 |
34 | public void setEncrptAESKey(String encrptAESKey) {
35 | this.encrptAESKey = encrptAESKey;
36 | }
37 |
38 | public String getEncryptAESClientData() {
39 | return encryptAESClientData;
40 | }
41 |
42 | public void setEncryptAESClientData(String encryptAESClientData) {
43 | this.encryptAESClientData = encryptAESClientData;
44 | }
45 |
46 | public String getSignData() {
47 | return signData;
48 | }
49 |
50 | public void setSignData(String signData) {
51 | this.signData = signData;
52 | }
53 |
54 | public String getRsaSignPublicKey() {
55 | return rsaSignPublicKey;
56 | }
57 |
58 | public void setRsaSignPublicKey(String rsaSignPublicKey) {
59 | this.rsaSignPublicKey = rsaSignPublicKey;
60 | }
61 |
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/test/java/license/szca/com/licensekeylibrary/AESTest.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 |
6 | import static org.junit.Assert.assertEquals;
7 |
8 | /**
9 | * description : AES测试类
10 | * author : JDNew
11 | * on : 2017/9/17.
12 | */
13 |
14 | public class AESTest {
15 |
16 | AESUtil aesUtil;
17 | //未加密数据
18 | String originData = "b8555645050517e860e0d09e8468a225159834bc9014e48b0d1572d7d18684241af9b8dc8c3d85416ce29e895f541c40554f33dd1a11ae0f4b62dbd6676f82c20758f28c4b750a05824284e76f770fb2d225fdbd48bcb6592095f657784bffcfd80e97ff101cf6f8f0e37815ee50cf46d7ad8481fcab5b8e0e294a16cbae33c4f5ddb80fb88f55273f2b14959f7bc56edbda56bf70c9ca8c88bf678929f1fed9039c8593455d41ee6ef9e25b1c99df3ee4f99be613ac077ca8197200f1833a42dfbe586c7307d2b1367089b8c5dce7312f5eae6418a5c8944fca99727ad87ca5fe823e11807e4616d464979263065f875a6cf669625f58dc3b320ac4383def899dfd3f5705af6413587acd3684cf5010f10b06d6d64131b8fa76ce2fcf5a01118010b26b6c90de8065bb31991a46d12c6baa6db9c729d1b74d2997a316b0daf6";
19 | @Before
20 | public void init(){
21 | aesUtil = new AESUtil();
22 | }
23 |
24 | @Test
25 | public void aesTest(){
26 |
27 | //aes加密
28 | byte[] encryptData = aesUtil.encryptData(originData.getBytes(), aesUtil.getAESSecretKey());
29 | //aes解密
30 | byte[] decryptData = aesUtil.decryptData(encryptData , aesUtil.getAESSecretKey());
31 |
32 | assertEquals(originData, new String(decryptData));
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/jdnew/serverapp/aidl/RootLicenseData.java:
--------------------------------------------------------------------------------
1 | package com.jdnew.serverapp.aidl;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | /**
7 | * description :
8 | * author : JDNew
9 | * on : 2017/9/24.
10 | */
11 |
12 | public class RootLicenseData implements Parcelable {
13 |
14 | private String license;
15 | private byte[] rsaPublicKey;
16 |
17 | public String getLicense() {
18 | return license;
19 | }
20 |
21 | public void setLicense(String license) {
22 | this.license = license;
23 | }
24 |
25 | public byte[] getRsaPublicKey() {
26 | return rsaPublicKey;
27 | }
28 |
29 | public void setRsaPublicKey(byte[] rsaPublicKey) {
30 | this.rsaPublicKey = rsaPublicKey;
31 | }
32 |
33 | public RootLicenseData(String license , byte[] rsaPublicKey){
34 | this.license = license;
35 | this.rsaPublicKey = rsaPublicKey;
36 | }
37 |
38 | protected RootLicenseData(Parcel in) {
39 | license = in.readString();
40 | rsaPublicKey = in.createByteArray();
41 | }
42 |
43 | public static final Creator CREATOR = new Creator() {
44 | @Override
45 | public RootLicenseData createFromParcel(Parcel in) {
46 | return new RootLicenseData(in);
47 | }
48 |
49 | @Override
50 | public RootLicenseData[] newArray(int size) {
51 | return new RootLicenseData[size];
52 | }
53 | };
54 |
55 | @Override
56 | public int describeContents() {
57 | return 0;
58 | }
59 |
60 | @Override
61 | public void writeToParcel(Parcel parcel, int i) {
62 | parcel.writeString(license);
63 | parcel.writeByteArray(rsaPublicKey);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/serverapp/src/main/java/com/jdnew/serverapp/aidl/RootLicenseData.java:
--------------------------------------------------------------------------------
1 | package com.jdnew.serverapp.aidl;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | /**
7 | * description :
8 | * author : JDNew
9 | * on : 2017/9/24.
10 | */
11 |
12 | public class RootLicenseData implements Parcelable {
13 |
14 | private String license;
15 | private byte[] rsaPublicKey;
16 |
17 | public String getLicense() {
18 | return license;
19 | }
20 |
21 | public void setLicense(String license) {
22 | this.license = license;
23 | }
24 |
25 | public byte[] getRsaPublicKey() {
26 | return rsaPublicKey;
27 | }
28 |
29 | public void setRsaPublicKey(byte[] rsaPublicKey) {
30 | this.rsaPublicKey = rsaPublicKey;
31 | }
32 |
33 | public RootLicenseData (String license , byte[] rsaPublicKey){
34 | this.license = license;
35 | this.rsaPublicKey = rsaPublicKey;
36 | }
37 |
38 | protected RootLicenseData(Parcel in) {
39 | license = in.readString();
40 | rsaPublicKey = in.createByteArray();
41 | }
42 |
43 | public static final Creator CREATOR = new Creator() {
44 | @Override
45 | public RootLicenseData createFromParcel(Parcel in) {
46 | return new RootLicenseData(in);
47 | }
48 |
49 | @Override
50 | public RootLicenseData[] newArray(int size) {
51 | return new RootLicenseData[size];
52 | }
53 | };
54 |
55 | @Override
56 | public int describeContents() {
57 | return 0;
58 | }
59 |
60 | @Override
61 | public void writeToParcel(Parcel parcel, int i) {
62 | parcel.writeString(license);
63 | parcel.writeByteArray(rsaPublicKey);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_regist.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
18 |
19 |
20 |
25 |
26 |
33 |
34 |
40 |
41 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/main/java/license/szca/com/licensekeylibrary/GetDeviceInfoUtil.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | import android.content.Context;
4 | import android.content.pm.PackageInfo;
5 | import android.content.pm.PackageManager;
6 | import android.util.Log;
7 |
8 | import org.spongycastle.util.encoders.Hex;
9 |
10 | import java.io.ByteArrayInputStream;
11 |
12 | import java.security.cert.CertificateFactory;
13 | import java.util.Iterator;
14 | import java.util.List;
15 | import java.util.UUID;
16 | import java.util.regex.Matcher;
17 | import java.util.regex.Pattern;
18 |
19 | import javax.security.cert.X509Certificate;
20 |
21 | /**
22 | * description 获取设备相关信息的工具类
23 | * Created by JD
24 | * on 2017/9/13.
25 | */
26 |
27 | public class GetDeviceInfoUtil {
28 |
29 |
30 | private Context mContext;
31 | public GetDeviceInfoUtil(Context context){
32 | mContext = context;
33 | }
34 | /**
35 | * 获取唯一标识码(每次安装app都是不一样的值)
36 | * 如:736519d5-4f7e-42fd-a6b0-66b74dff4657
37 | *
38 | * @return 返回过滤掉“-”的标识码
39 | * 736519d54f7e42fda6b066b74dff4657
40 | */
41 | public String getUUID() {
42 | String regularExpression = "-";
43 | Pattern pattern = Pattern.compile(regularExpression);
44 | Matcher matcher = pattern.matcher(UUID.randomUUID().toString());
45 | return matcher.replaceAll("").trim();
46 | }
47 |
48 | /**
49 | * 获取应用包名
50 | * @return
51 | */
52 | public String getAppPackageName() {
53 | return mContext.getPackageName();
54 | }
55 |
56 | /**
57 | * 获取应用签名
58 | * @return
59 | */
60 | public String getSign() {
61 | PackageManager pm = mContext.getPackageManager();
62 | List apps = pm
63 | .getInstalledPackages(PackageManager.GET_SIGNATURES);
64 | Iterator iter = apps.iterator();
65 |
66 | while (iter.hasNext()) {
67 | PackageInfo info = iter.next();
68 | String packageName = info.packageName;
69 | //按包名 取签名
70 | if (packageName.equals(getAppPackageName())) {
71 | byte[] signByte = info.signatures[0].toByteArray();
72 |
73 | return new String( Hex.encode(signByte));
74 |
75 | }
76 | }
77 | return null;
78 | }
79 |
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | 1.8
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 项目结构
2 | ## app
3 | 主要是用于用户输入信息
4 |
5 | ## licensekeylibrary
6 | 是一个库,里面放着加密,解密的封装,以及其它一些数据的生成
7 |
8 | ## serverapp
9 | 主要是对客户端提交的用户输入信息进行证书的生成和校验
10 |
11 | 注:在运行的时候必需保证客户端和服务端两个app都已经安装在手机上,我这里没做判断,在之后会做多一层判断。
12 |
13 | app和serverapp之间的通信是用AIDL的方式进行,在一开始我是用Messenger来做的(Messenger的底层也是AIDL,这里一开始为了方便就用Messenger),所以你可以看到有RegsitActivity和RegistActivity1,前者是用Messenger,后者就是用AIDL,所以可以做些适当的修改进行切换。
14 |
15 | 另我也对此写了相关博客
16 |
17 | [Android之使用AIDL进行IPC(一)](http://blog.csdn.net/u013066292/article/details/78083755)
18 |
19 | # 序列图
20 | ```sequence
21 | app->serverapp: 提交生成证书的数据
22 | Note right of serverapp: 对数据进行处理
23 | serverapp-->app: 返回证书
24 | app->serverapp: 提交校验数据
25 | Note right of serverapp: 对数据进行校验
26 | serverapp-->app: 返回校验结果
27 | ```
28 |
29 | # 客户端流程图
30 |
31 | ```flow
32 |
33 | start=>start: 开始
34 | end=>end: 结束
35 |
36 | opGetDeviceInfo=>operation: 获取设备信息(uuid,包名)
37 | opInputUserName=>operation: 用户输入“abc”
38 | opGenLicenseData=>operation: 将用户输入和设备信息拼接起来
39 | opSendLicenseData=>operation: 将拼接数据发给服务端
40 | opGetLicense=>operation: 得到客户端返回的证书和RSA公钥
41 | opCombimeDataWithLicense=>operation: 将license和用户输入,设备信息生成json(data)
42 | opAESWithData=>operation: 用AES对data加密
43 | opRSAWithAESKey=>operation: 用RSA公钥对AES的密钥加密
44 | opRSASignData=>operation: 用RSA对数据进行签名
45 | opGenSubmitData=>operation: 将加密后的data,加密后的AES密钥,RSA签名公钥和签名拼接成json(submitData)
46 | opSendToServer=>operation: 将submitData提交给服务端
47 |
48 | start->opGetDeviceInfo->opInputUserName->opGenLicenseData->opSendLicenseData->opGetLicense->opCombimeDataWithLicense->opAESWithData->opRSAWithAESKey->opGenSubmitData->opSendToServer->end
49 |
50 | ```
51 | # 服务端流程图
52 |
53 | ```flow
54 |
55 | start=>start: 开始
56 | end=>end: 结束
57 | opGenRSAKey=>operation: 生成RSA公钥和密钥
58 | opReceiveData=>operation: 接收到来自客户端的数据
59 | opSHA1WithData=>operation: 使用SHA1对拼接后的数据做摘要
60 | opHexWithData=>operation: 对摘要后的数据做Hex
61 | opGenLicense=>operation: 得到要填写的证书(20位,字母和数字构成)
62 | opReplyLicense=>operation: 把证书和RSA公钥发给客户端
63 | opReceiveSubmitData=>operation: 接收客户端发来的submitData
64 | opRSADecryptAESKey=>operation: 用RSA公钥解密出AES密钥
65 | opAESDecryptData=>operation: 用AES密钥解密出data
66 | opCompareLicense=>operation: 将Hex后的数据与data里的license做对比
67 | conLicense=>condition: 对比一致?
68 | conSign=>condition: 签名校验成功?
69 | opReplySuccess=>operation: 注册成功
70 | opReplyFailed=>operation: 注册失败
71 |
72 | start->opGenRSAKey->opReceiveData->opSHA1WithData->opHexWithData->opGenLicense->opReplyLicense->opReceiveSubmitData->opRSADecryptAESKey->opAESDecryptData->opCompareLicense->conLicense
73 | conLicense(yes)->conSign
74 | conLicense(no)->opReplyFailed->end
75 | conSign(yes)->opReplySuccess->end
76 | conSign(no)->opReplyFailed->end
77 |
78 | ```
79 |
80 |
81 |
82 |
83 | 
84 | 
85 | 
86 |
--------------------------------------------------------------------------------
/app/src/main/java/license/szca/com/licenseapp/presenter/RegistPresenter1.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp.presenter;
2 |
3 | import android.app.Activity;
4 | import android.content.ComponentName;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.ServiceConnection;
8 | import android.os.IBinder;
9 | import android.os.RemoteException;
10 | import android.text.TextUtils;
11 |
12 | import com.jdnew.serverapp.aidl.ILicense;
13 | import com.jdnew.serverapp.aidl.RootLicenseData;
14 |
15 | import license.szca.com.licenseapp.view.IRegistView1;
16 | import license.szca.com.licensekeylibrary.GenLicenseKeyUtil;
17 |
18 | /**
19 | * description :
20 | * author : JDNew
21 | * on : 2017/9/24.
22 | */
23 |
24 | public class RegistPresenter1 {
25 |
26 | private Activity mContext;
27 | private IRegistView1 mIRegistView1;
28 | private GenLicenseKeyUtil genLicenseKeyUtil;
29 | private byte[] mRSAPublicKey;
30 |
31 |
32 |
33 | public RegistPresenter1(Activity context , IRegistView1 iRegistView1){
34 | this.mContext = context;
35 | this.mIRegistView1 = iRegistView1;
36 | genLicenseKeyUtil = new GenLicenseKeyUtil(mContext);
37 |
38 | Intent intent = new Intent();
39 | intent.setAction("com.jdnew.serverapp.service.LicenseService");
40 | intent.setPackage("com.jdnew.serverapp");
41 | mContext.bindService(intent , mServiceConnection , Context.BIND_AUTO_CREATE);
42 |
43 |
44 |
45 |
46 | }
47 |
48 | public void genLicenseKey(String name) {
49 | if (TextUtils.isEmpty(name)) {
50 | mIRegistView1.getLicenseKeyFailed("请输入用户名");
51 | return;
52 | }
53 |
54 | mIRegistView1.showLoading("正在获取证书");
55 | try {
56 |
57 | RootLicenseData rootLicenseData = mILicense.returnLicense(genLicenseKeyUtil.getDataToGenLicense(name)) ;
58 | mIRegistView1.getLicenseKeySuccess(rootLicenseData.getLicense());
59 | mRSAPublicKey = rootLicenseData.getRsaPublicKey();
60 |
61 | } catch (RemoteException e) {
62 | e.printStackTrace();
63 | }
64 | }
65 |
66 | public void submitData(String licenseKey) {
67 | if (TextUtils.isEmpty(licenseKey)) {
68 | mIRegistView1.checkLicenseKeyFailed("请输入证书");
69 | return;
70 | }
71 |
72 | String submitData = genLicenseKeyUtil.getSubmitData(licenseKey , mRSAPublicKey);
73 |
74 | try {
75 | String result = mILicense.returnCheckResult(submitData);
76 | if (result.equals("true")) {
77 | mIRegistView1.checkLicenseKeySuccess("验证成功");
78 | }else {
79 | mIRegistView1.checkLicenseKeyFailed("验证失败");
80 | }
81 |
82 |
83 | } catch (RemoteException e) {
84 | e.printStackTrace();
85 | }
86 | }
87 |
88 | public void onStop() {
89 |
90 | }
91 |
92 |
93 |
94 | private ILicense mILicense;
95 | private ServiceConnection mServiceConnection = new ServiceConnection() {
96 | @Override
97 | public void onServiceConnected(ComponentName name, IBinder service) {
98 | mILicense = ILicense.Stub.asInterface(service);
99 | }
100 |
101 | @Override
102 | public void onServiceDisconnected(ComponentName name) {
103 |
104 | }
105 | };
106 | }
107 |
--------------------------------------------------------------------------------
/app/src/main/java/license/szca/com/licenseapp/activity/RegistActivity.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp.activity;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.view.View;
9 | import android.widget.Button;
10 | import android.widget.EditText;
11 | import android.widget.Toast;
12 |
13 | import license.szca.com.licenseapp.R;
14 | import license.szca.com.licenseapp.presenter.RegistPresenter;
15 | import license.szca.com.licenseapp.view.IRegistView;
16 |
17 | /**
18 | * description 注册页面
19 | * Created by JD
20 | * on 2017/9/12.
21 | */
22 | public class RegistActivity extends AppCompatActivity implements View.OnClickListener, IRegistView {
23 |
24 | private EditText et_input_name;
25 | private Button bt_gen;
26 | private EditText et_key;
27 | private Button bt_check;
28 | private RegistPresenter registPresenter;
29 | private final String TAG = "RegistActivity";
30 |
31 |
32 | @Override
33 | protected void onCreate(@Nullable Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.activity_regist);
36 |
37 | initView();
38 | }
39 |
40 | @Override
41 | protected void onStart() {
42 | super.onStart();
43 | registPresenter = new RegistPresenter(this, this);
44 | }
45 |
46 | @Override
47 | protected void onStop() {
48 | super.onStop();
49 | registPresenter.onStop();
50 | }
51 |
52 | private void initView() {
53 | et_input_name = (EditText) findViewById(R.id.et_input_name);
54 | bt_gen = (Button) findViewById(R.id.bt_gen);
55 | et_key = (EditText) findViewById(R.id.et_key);
56 | bt_check = (Button) findViewById(R.id.bt_check);
57 |
58 | bt_gen.setOnClickListener(this);
59 | bt_check.setOnClickListener(this);
60 |
61 |
62 |
63 | }
64 |
65 | @Override
66 | public void onClick(View v) {
67 | switch (v.getId()) {
68 | case R.id.bt_gen:
69 | registPresenter.genLicenseKey(et_input_name.getText().toString().trim());
70 | break;
71 | case R.id.bt_check:
72 | registPresenter.submitData(et_key.getText().toString().trim());
73 | break;
74 | }
75 | }
76 |
77 |
78 | @Override
79 | public void getLicenseKeyFailed(String msg) {
80 | dismissProgressDialog();
81 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
82 | }
83 |
84 | @Override
85 | public void getLicenseKeySuccess(String key) {
86 | dismissProgressDialog();
87 | et_key.setText(key);
88 | }
89 |
90 | @Override
91 | public void checkLicenseKeySuccess(String msg) {
92 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
93 | startActivity(new Intent(this, RegistSuccessActivity.class));
94 | finish();
95 | }
96 |
97 | @Override
98 | public void checkLicenseKeyFailed(String msg) {
99 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
100 | }
101 |
102 |
103 | @Override
104 | public void showLoading(String msg) {
105 | showProgressDialog(msg);
106 | }
107 |
108 |
109 | private ProgressDialog progressDialog;
110 |
111 | /**
112 | * 显示加载窗口
113 | * @param msg
114 | */
115 | private void showProgressDialog(String msg) {
116 | progressDialog = new ProgressDialog(this);
117 | progressDialog.setMessage(msg);
118 | progressDialog.show();
119 | }
120 |
121 | /**
122 | * 隐藏加载窗口
123 | */
124 | private void dismissProgressDialog() {
125 | if (progressDialog != null && progressDialog.isShowing()) {
126 | progressDialog.dismiss();
127 | progressDialog = null;
128 | }
129 | }
130 |
131 | }
132 |
133 |
--------------------------------------------------------------------------------
/app/src/main/java/license/szca/com/licenseapp/activity/RegistActivity1.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp.activity;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.view.View;
9 | import android.widget.Button;
10 | import android.widget.EditText;
11 | import android.widget.Toast;
12 |
13 | import license.szca.com.licenseapp.R;
14 | import license.szca.com.licenseapp.presenter.RegistPresenter;
15 | import license.szca.com.licenseapp.presenter.RegistPresenter1;
16 | import license.szca.com.licenseapp.view.IRegistView;
17 | import license.szca.com.licenseapp.view.IRegistView1;
18 |
19 | /**
20 | * description :
21 | * author : JDNew
22 | * on : 2017/9/24.
23 | */
24 |
25 | public class RegistActivity1 extends AppCompatActivity implements View.OnClickListener, IRegistView1 {
26 |
27 | private EditText et_input_name;
28 | private Button bt_gen;
29 | private EditText et_key;
30 | private Button bt_check;
31 | private RegistPresenter1 registPresenter;
32 | private final String TAG = "RegistActivity1";
33 |
34 |
35 | @Override
36 | protected void onCreate(@Nullable Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 | setContentView(R.layout.activity_regist);
39 |
40 | initView();
41 | }
42 |
43 | @Override
44 | protected void onStart() {
45 | super.onStart();
46 | registPresenter = new RegistPresenter1(this, this);
47 | }
48 |
49 | @Override
50 | protected void onStop() {
51 | super.onStop();
52 | registPresenter.onStop();
53 | }
54 |
55 | private void initView() {
56 | et_input_name = (EditText) findViewById(R.id.et_input_name);
57 | bt_gen = (Button) findViewById(R.id.bt_gen);
58 | et_key = (EditText) findViewById(R.id.et_key);
59 | bt_check = (Button) findViewById(R.id.bt_check);
60 |
61 | bt_gen.setOnClickListener(this);
62 | bt_check.setOnClickListener(this);
63 |
64 |
65 |
66 | }
67 |
68 | @Override
69 | public void onClick(View v) {
70 | switch (v.getId()) {
71 | case R.id.bt_gen:
72 | registPresenter.genLicenseKey(et_input_name.getText().toString().trim());
73 | break;
74 | case R.id.bt_check:
75 | registPresenter.submitData(et_key.getText().toString().trim());
76 | break;
77 | }
78 | }
79 |
80 |
81 | @Override
82 | public void getLicenseKeyFailed(String msg) {
83 | dismissProgressDialog();
84 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
85 | }
86 |
87 | @Override
88 | public void getLicenseKeySuccess(String key) {
89 | dismissProgressDialog();
90 | et_key.setText(key);
91 | }
92 |
93 | @Override
94 | public void checkLicenseKeySuccess(String msg) {
95 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
96 | startActivity(new Intent(this, RegistSuccessActivity.class));
97 | finish();
98 | }
99 |
100 | @Override
101 | public void checkLicenseKeyFailed(String msg) {
102 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
103 | }
104 |
105 |
106 | @Override
107 | public void showLoading(String msg) {
108 | showProgressDialog(msg);
109 | }
110 |
111 |
112 | private ProgressDialog progressDialog;
113 |
114 | /**
115 | * 显示加载窗口
116 | * @param msg
117 | */
118 | private void showProgressDialog(String msg) {
119 | progressDialog = new ProgressDialog(this);
120 | progressDialog.setMessage(msg);
121 | progressDialog.show();
122 | }
123 |
124 | /**
125 | * 隐藏加载窗口
126 | */
127 | private void dismissProgressDialog() {
128 | if (progressDialog != null && progressDialog.isShowing()) {
129 | progressDialog.dismiss();
130 | progressDialog = null;
131 | }
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/main/java/license/szca/com/licensekeylibrary/AESUtil.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | import java.security.InvalidKeyException;
4 | import java.security.Key;
5 | import java.security.NoSuchAlgorithmException;
6 | import java.security.NoSuchProviderException;
7 | import java.security.Security;
8 |
9 | import javax.crypto.BadPaddingException;
10 | import javax.crypto.Cipher;
11 | import javax.crypto.IllegalBlockSizeException;
12 | import javax.crypto.KeyGenerator;
13 | import javax.crypto.NoSuchPaddingException;
14 | import javax.crypto.SecretKey;
15 | import javax.crypto.spec.SecretKeySpec;
16 |
17 | /**
18 | * description : aes对称加密工具类
19 | * author : JDNew
20 | * on : 2017/9/17.
21 | */
22 |
23 | public class AESUtil {
24 |
25 | private final String KEY_ALGORITEM = "AES";
26 | private final String CIPHER_ALGORITEM = "AES/ECB/PKCS7Padding";
27 | private SecretKey mSecretKey;
28 |
29 | static {
30 | //从位置1开始,添加新的提供者
31 | Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
32 | }
33 |
34 | public AESUtil() {
35 | initKey();
36 | }
37 |
38 | /**
39 | * 生成加密的密钥
40 | */
41 | private void initKey() {
42 | try {
43 | KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITEM, "SC");
44 | keyGenerator.init(128);
45 | mSecretKey = keyGenerator.generateKey();
46 |
47 | } catch (NoSuchAlgorithmException e) {
48 | e.printStackTrace();
49 | } catch (NoSuchProviderException e) {
50 | e.printStackTrace();
51 | }
52 | }
53 |
54 | /**
55 | * aes加密数据
56 | * @param data 要加密的数据
57 | * @param keyByte 二进制密钥
58 | * @return
59 | */
60 | public byte[] encryptData(byte[] data, byte[] keyByte) {
61 | byte[] enryptResult = null;
62 | Key key = genKey(keyByte);
63 |
64 | try {
65 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITEM, "SC");
66 | cipher.init(Cipher.ENCRYPT_MODE, key);
67 |
68 | enryptResult = cipher.doFinal(data);
69 |
70 |
71 | } catch (NoSuchAlgorithmException e) {
72 | e.printStackTrace();
73 | } catch (NoSuchPaddingException e) {
74 | e.printStackTrace();
75 | } catch (InvalidKeyException e) {
76 | e.printStackTrace();
77 | } catch (BadPaddingException e) {
78 | e.printStackTrace();
79 | } catch (IllegalBlockSizeException e) {
80 | e.printStackTrace();
81 | } catch (NoSuchProviderException e) {
82 | e.printStackTrace();
83 | }
84 | return enryptResult;
85 | }
86 |
87 | /**
88 | * aes解密数据
89 | * @param data 要解密的数据
90 | * @param keyByte 二进制密钥
91 | * @return
92 | */
93 | public byte[] decryptData(byte[] data, byte[] keyByte) {
94 |
95 | Key key = genKey(keyByte);
96 | byte[] decryptResult = null;
97 | try {
98 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITEM, "SC");
99 | cipher.init(Cipher.DECRYPT_MODE, key);
100 | decryptResult = cipher.doFinal(data);
101 | } catch (NoSuchAlgorithmException e) {
102 | e.printStackTrace();
103 | } catch (NoSuchPaddingException e) {
104 | e.printStackTrace();
105 | } catch (InvalidKeyException e) {
106 | e.printStackTrace();
107 | } catch (BadPaddingException e) {
108 | e.printStackTrace();
109 | } catch (IllegalBlockSizeException e) {
110 | e.printStackTrace();
111 | } catch (NoSuchProviderException e) {
112 | e.printStackTrace();
113 | }
114 |
115 | return decryptResult;
116 | }
117 |
118 | /**
119 | * 获取aes加密的密钥
120 | *
121 | * @return 二进制密钥
122 | */
123 | public byte[] getAESSecretKey() {
124 | return mSecretKey.getEncoded();
125 | }
126 |
127 | /**
128 | * 转换密钥 通过二进制转换
129 | *
130 | * @param keyByte 二进制密钥
131 | * @return 密钥
132 | */
133 | private Key genKey(byte[] keyByte) {
134 | SecretKey secretKey = new SecretKeySpec(keyByte, KEY_ALGORITEM);
135 | return secretKey;
136 | }
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/serverapp/src/main/java/com/jdnew/serverapp/service/LicenseService.java:
--------------------------------------------------------------------------------
1 | package com.jdnew.serverapp.service;
2 |
3 | import android.app.Service;
4 | import android.content.Intent;
5 | import android.os.Binder;
6 | import android.os.IBinder;
7 | import android.os.RemoteException;
8 | import android.support.annotation.Nullable;
9 | import android.util.Log;
10 |
11 | import com.google.gson.Gson;
12 | import com.jdnew.serverapp.aidl.ILicense;
13 | import com.jdnew.serverapp.aidl.RootLicenseData;
14 |
15 | import org.spongycastle.util.encoders.Hex;
16 |
17 | import license.szca.com.licensekeylibrary.AESUtil;
18 | import license.szca.com.licensekeylibrary.CodeUtil;
19 | import license.szca.com.licensekeylibrary.RSAUtil;
20 | import license.szca.com.licensekeylibrary.RootData;
21 | import license.szca.com.licensekeylibrary.RootSubmitData;
22 | import license.szca.com.licensekeylibrary.SHAUtil;
23 |
24 |
25 | /**
26 | * description :
27 | * author : JDNew
28 | * on : 2017/9/24.
29 | */
30 |
31 | public class LicenseService extends Service {
32 |
33 | private SHAUtil shaUtil;
34 | private CodeUtil codeUtil;
35 | private RSAUtil rsaUtil;
36 | private AESUtil aesUtil;
37 | private RootLicenseData rootLicenseData;
38 | private final String TAG = "LicenseService";
39 | private Binder linsenseBinder = new ILicense.Stub() {
40 |
41 | @Override
42 | public com.jdnew.serverapp.aidl.RootLicenseData returnLicense(String licenseData) throws RemoteException {
43 |
44 | byte[] sha1Data = shaUtil.encodeSHA1(licenseData.getBytes());
45 | String licenseKey = codeUtil.hexData(sha1Data);
46 | //获取RSA的公钥
47 | byte[] rsaPublicKey = rsaUtil.getPublicKey();
48 | RootLicenseData rootLicenseData = new RootLicenseData(licenseKey, rsaPublicKey);
49 |
50 | return rootLicenseData;
51 | }
52 |
53 | @Override
54 | public String returnCheckResult(String submitData) throws RemoteException {
55 |
56 | Gson gson = new Gson();
57 | RootSubmitData rootSubmitData = gson.fromJson(submitData, RootSubmitData.class);
58 | byte[] aesKey = Hex.decode(rootSubmitData.getEncrptAESKey());
59 | byte[] encryptClientData = Hex.decode(rootSubmitData.getEncryptAESClientData());
60 | byte[] signData = Hex.decode(rootSubmitData.getSignData());
61 | byte[] rsaSignPublicKey = Hex.decode(rootSubmitData.getRsaSignPublicKey());
62 |
63 |
64 | //用RSA私钥解密出AES密钥
65 | byte[] aesKeyByte = rsaUtil.decryptWithPrivateKey(aesKey, rsaUtil.getPrivateKey());
66 | //用AES密钥解密出客户端数据
67 | byte[] decryptClientData = aesUtil.decryptData(encryptClientData, aesKeyByte);
68 | String result = new String(Hex.decode(decryptClientData));
69 | Log.d(TAG, result);
70 |
71 | if (isLicenseEqual(result) && isSignCorrect(result, signData, rsaSignPublicKey)) {
72 | return "true";
73 | } else {
74 | return "false";
75 | }
76 |
77 | }
78 | };
79 |
80 | /**
81 | * 签名校验结果
82 | *
83 | * @param result
84 | * @param signData
85 | * @param rsaSignPublicKey
86 | * @return
87 | */
88 | private boolean isSignCorrect(String result, byte[] signData, byte[] rsaSignPublicKey) {
89 | return rsaUtil.verify(result.getBytes(), rsaSignPublicKey, signData);
90 | }
91 |
92 | /**
93 | * 校验客户端传过来的证书和服务端生成的证书是否一致
94 | *
95 | * @param result
96 | * @return
97 | */
98 | private boolean isLicenseEqual(String result) {
99 | Gson gson = new Gson();
100 | RootData rootData = gson.fromJson(result, RootData.class);
101 | String data = rootData.getUserName()
102 | + rootData.getUuid()
103 | + rootData.getApplicationId();
104 | String newLicense = codeUtil.hexData(
105 | shaUtil.encodeSHA1(data.getBytes())
106 | );
107 | //判断由username,uuid和applicationId拼接并哈希后的值与客户端传过来的证书是否一致
108 | if (newLicense.equals(rootData.getLicenseKey())) {
109 | Log.d(TAG, "校验成功");
110 | return true;
111 |
112 | } else {
113 | Log.d(TAG, "校验失败");
114 | return false;
115 | }
116 | }
117 |
118 |
119 | @Nullable
120 | @Override
121 | public IBinder onBind(Intent intent) {
122 | return linsenseBinder;
123 | }
124 |
125 | @Override
126 | public void onCreate() {
127 | super.onCreate();
128 | shaUtil = new SHAUtil();
129 | rsaUtil = new RSAUtil();
130 | codeUtil = new CodeUtil();
131 | aesUtil = new AESUtil();
132 | rsaUtil.initPrivateAndPublicKey();
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/main/java/license/szca/com/licensekeylibrary/GenLicenseKeyUtil.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | import android.content.Context;
4 |
5 | import org.json.JSONException;
6 | import org.json.JSONObject;
7 | import org.spongycastle.util.encoders.Hex;
8 |
9 | import java.security.Security;
10 |
11 | /**
12 | * description
13 | * Created by JD
14 | * on 2017/9/12.
15 | */
16 |
17 | public class GenLicenseKeyUtil {
18 |
19 | static {
20 | //从位置1开始,添加新的提供者
21 | Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
22 | }
23 |
24 | private final String TAG = "GenLicenseKeyUtil";
25 |
26 | private GetDeviceInfoUtil getDeviceInfoUtil;
27 | private Context mContext;
28 | private String mLicenseKey = null;
29 | private String mAppSignature = null;
30 | private CodeUtil codeUtil;
31 | private RSAUtil rsaUtil;
32 | private SHAUtil shaUtil;
33 | private RootData mRootData;
34 | private AESUtil aesUtil;
35 |
36 | public GenLicenseKeyUtil(Context context) {
37 | mContext = context;
38 | getDeviceInfoUtil = new GetDeviceInfoUtil(mContext);
39 | codeUtil = new CodeUtil();
40 | rsaUtil = new RSAUtil();
41 | shaUtil = new SHAUtil();
42 | aesUtil = new AESUtil();
43 | mRootData = new RootData();
44 | //1.初始化密钥和公钥
45 | rsaUtil.initPrivateAndPublicKey();
46 | }
47 |
48 |
49 |
50 | /**
51 | * 获取要提交给服务端生成证书的数据
52 | * @param input
53 | * @return
54 | */
55 | public String getDataToGenLicense(String input){
56 |
57 | mRootData.setUserName(input);
58 | mRootData.setUuid(getDeviceInfoUtil.getUUID());
59 | mRootData.setApplicationId(getDeviceInfoUtil.getAppPackageName());
60 |
61 | return mRootData.getUserName() + mRootData.getUuid() + mRootData.getApplicationId();
62 | }
63 |
64 | /**
65 | * 获取要提交给服务端校验的数据
66 | *
67 | * @return
68 | */
69 | public String getSubmitData(String licenseKey, byte[] RSAPublicKey) {
70 |
71 | //获取要提交的客户端数据
72 | String clientData = genClientData(licenseKey);
73 | //由于数据过长,无法进行RSA加密,所以使用AES加密客户端数据
74 | byte[] aesEncryptClientByte = aesUtil.encryptData(Hex.encode(clientData.getBytes()) , aesUtil.getAESSecretKey());
75 | //获取AES的加密密钥
76 | byte[] aesKey = aesUtil.getAESSecretKey();
77 | //用服务端发过来的RSA公钥对AES的密钥进行加密
78 | byte[] encryptAESKey = rsaUtil.encryptWithPublicKey(aesKey , RSAPublicKey);
79 | //使用RSA对数据进行签名
80 | byte[] signData = rsaUtil.signWithPrivateKey(clientData.getBytes() , rsaUtil.getPrivateKey());
81 | //获取RSA的公钥
82 | byte[] rsaSignPublicKey = rsaUtil.getPublicKey();
83 |
84 |
85 | //对aes加密后客户端数据,aes密钥,rsa公钥三者打包成json返回
86 | String submitData = genSubmitData(aesEncryptClientByte , encryptAESKey , signData , rsaSignPublicKey);
87 |
88 |
89 | return submitData;
90 |
91 | }
92 |
93 | /**
94 | * 转换成json,提交给服务端的数据
95 | * @param clientData 被AES加密过的数据
96 | * @param encryptAESKey AES密钥,用于解密出客户端数据
97 | * @param signData 签名后的数据
98 | *@param rsaSignPublicKey RSA签名公钥
99 | * @return
100 | */
101 | private String genSubmitData(byte[] clientData, byte[] encryptAESKey, byte[] signData, byte[] rsaSignPublicKey) {
102 | RootSubmitData rootSubmitData = new RootSubmitData();
103 | rootSubmitData.setEncryptAESClientData(new String(Hex.encode(clientData)));
104 | rootSubmitData.setEncrptAESKey(new String(Hex.encode(encryptAESKey)));
105 | rootSubmitData.setSignData(new String(Hex.encode(signData)));
106 | rootSubmitData.setRsaSignPublicKey(new String(Hex.encode(rsaSignPublicKey)));
107 |
108 |
109 | JSONObject jsonObject = new JSONObject();
110 | try {
111 | jsonObject.put("encryptAESClientData" , rootSubmitData.getEncryptAESClientData());
112 | jsonObject.put("encrptAESKey" , rootSubmitData.getEncrptAESKey());
113 | jsonObject.put("signData" , rootSubmitData.getSignData());
114 | jsonObject.put("rsaSignPublicKey" , rootSubmitData.getRsaSignPublicKey());
115 |
116 | } catch (JSONException e) {
117 | e.printStackTrace();
118 | }
119 |
120 |
121 | return jsonObject.toString();
122 | }
123 |
124 |
125 |
126 |
127 | /**
128 | * 生成客户端数据,即在用户名,uuid,applicaitonId的基础上
129 | * 加入证书
130 | *
131 | * @return
132 | */
133 | private String genClientData(String licenseKey) {
134 |
135 |
136 | mRootData.setLicenseKey(licenseKey);
137 | // mRootData.setAppSignture(getDeviceInfoUtil.getSign());
138 | JSONObject jsonObject = new JSONObject();
139 | try {
140 | jsonObject.put("userName", mRootData.getUserName());
141 | jsonObject.put("uuid", mRootData.getUuid());
142 | jsonObject.put("applicationId", mRootData.getApplicationId());
143 | jsonObject.put("licenseKey", mRootData.getLicenseKey());
144 | // jsonObject.put("appSignature", mRootData.getAppSignture());
145 |
146 | } catch (JSONException e) {
147 | e.printStackTrace();
148 | }
149 |
150 |
151 | return jsonObject.toString();
152 | }
153 |
154 |
155 |
156 |
157 | }
158 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/java/license/szca/com/licenseapp/presenter/RegistPresenter.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp.presenter;
2 |
3 | import android.app.Activity;
4 | import android.content.ComponentName;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.ServiceConnection;
8 | import android.os.Bundle;
9 | import android.os.Handler;
10 | import android.os.IBinder;
11 | import android.os.Message;
12 | import android.os.Messenger;
13 | import android.os.RemoteException;
14 | import android.text.TextUtils;
15 | import android.util.Log;
16 |
17 | import license.szca.com.licenseapp.service.BackService;
18 | import license.szca.com.licenseapp.view.IRegistView;
19 | import license.szca.com.licensekeylibrary.GenLicenseKeyUtil;
20 |
21 | import static license.szca.com.licenseapp.common.Constant.MSG_CHECK_LICENSE;
22 | import static license.szca.com.licenseapp.common.Constant.MSG_GET_LICENSE;
23 |
24 | /**
25 | * description
26 | * Created by JD
27 | * on 2017/9/12.
28 | */
29 |
30 | public class RegistPresenter {
31 |
32 | private final String TAG = "RegistPresenter";
33 | private Activity mContext;
34 | private IRegistView mIRegistView;
35 | private GenLicenseKeyUtil genLicenseKeyUtil;
36 | private byte[] mRSAPublicKey;
37 | private Messenger mToServiceMessenger;
38 | private Messenger mReplyMessenger = new Messenger(new replyHandler());
39 |
40 |
41 |
42 | //处理服务端返回的结果
43 | private class replyHandler extends Handler {
44 | @Override
45 | public void handleMessage(Message msg) {
46 | switch (msg.what){
47 | //返回证书和RSA公钥
48 | case MSG_GET_LICENSE:
49 | String license = msg.getData().getString("license");
50 | mRSAPublicKey = msg.getData().getByteArray("rsaPublicKey");
51 | //填写到证书输入框里
52 | mIRegistView.getLicenseKeySuccess(license);
53 | break;
54 | //返回校验结果
55 | case MSG_CHECK_LICENSE:
56 | boolean isSuccess = msg.getData().getBoolean("success");
57 | if (isSuccess) {
58 | Log.d(TAG , "注册成功");
59 | mIRegistView.checkLicenseKeySuccess("注册成功");
60 | }else {
61 | mIRegistView.checkLicenseKeyFailed("注册失败");
62 | Log.d(TAG , "注册失败");
63 | }
64 | break;
65 | }
66 |
67 |
68 | }
69 | }
70 |
71 | private ServiceConnection serviceConnection = new ServiceConnection() {
72 | @Override
73 | public void onServiceConnected(ComponentName name, IBinder service) {
74 | mToServiceMessenger = new Messenger(service);
75 | }
76 |
77 | @Override
78 | public void onServiceDisconnected(ComponentName name) {
79 |
80 | }
81 | };
82 |
83 |
84 | public RegistPresenter(Activity context, IRegistView iRegistView) {
85 | this.mContext = context;
86 | this.mIRegistView = iRegistView;
87 | genLicenseKeyUtil = new GenLicenseKeyUtil(mContext);
88 | //绑定服务
89 | Intent intent = new Intent(mContext, BackService.class);
90 | mContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
91 |
92 | }
93 |
94 | public void onStop() {
95 | mContext.unbindService(serviceConnection);
96 | }
97 |
98 | /**
99 | * 获取证书
100 | *
101 | * @param name
102 | */
103 | public void genLicenseKey(String name) {
104 | if (TextUtils.isEmpty(name)) {
105 | mIRegistView.getLicenseKeyFailed("请输入用户名");
106 | return;
107 | }
108 |
109 | mIRegistView.showLoading("正在获取证书");
110 | callServiceToGetLicense(name);
111 |
112 | }
113 |
114 | /**
115 | * 发送用户数据给服务端,让服务端生成证书
116 | *
117 | * @param input
118 | */
119 | private void callServiceToGetLicense(String input) {
120 | try {
121 | Message message = new Message();
122 | Bundle bundle = new Bundle();
123 | bundle.putString("userData", genLicenseKeyUtil.getDataToGenLicense(input));
124 | message.what = MSG_GET_LICENSE;
125 | message.setData(bundle);
126 | message.replyTo = mReplyMessenger;
127 | mToServiceMessenger.send(message);
128 | } catch (RemoteException e) {
129 | e.printStackTrace();
130 | }
131 | }
132 |
133 |
134 |
135 | /**
136 | * 提交处理后的数据给服务端校验
137 | * @param licenseKey
138 | * @return
139 | */
140 | public void submitData(String licenseKey) {
141 | if (TextUtils.isEmpty(licenseKey)) {
142 | mIRegistView.checkLicenseKeyFailed("请输入证书");
143 | return;
144 | }
145 |
146 | mIRegistView.showLoading("正在校验");
147 | String submitData = genLicenseKeyUtil.getSubmitData(licenseKey , mRSAPublicKey);
148 |
149 | callServiceToCheck(submitData);
150 | }
151 |
152 | /**
153 | * 通知服务端校验
154 | * @param submitData 提交的数据
155 | */
156 | private void callServiceToCheck(String submitData) {
157 | try {
158 | Message message = new Message();
159 | Bundle bundle = new Bundle();
160 | bundle.putString("submitData" , submitData);
161 | message.what = MSG_CHECK_LICENSE;
162 | message.replyTo = mReplyMessenger;
163 | message.setData(bundle);
164 | mToServiceMessenger.send(message);
165 | } catch (RemoteException e) {
166 | e.printStackTrace();
167 | }
168 | }
169 |
170 |
171 | }
172 |
--------------------------------------------------------------------------------
/app/src/main/java/license/szca/com/licenseapp/service/BackService.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licenseapp.service;
2 |
3 | import android.app.Service;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.os.Handler;
7 | import android.os.IBinder;
8 | import android.os.Message;
9 | import android.os.Messenger;
10 | import android.os.RemoteException;
11 | import android.support.annotation.Nullable;
12 | import android.util.Log;
13 |
14 | import com.google.gson.Gson;
15 |
16 | import org.spongycastle.util.encoders.Hex;
17 |
18 | import license.szca.com.licensekeylibrary.AESUtil;
19 | import license.szca.com.licensekeylibrary.CodeUtil;
20 | import license.szca.com.licensekeylibrary.RSAUtil;
21 | import license.szca.com.licensekeylibrary.RootData;
22 | import license.szca.com.licensekeylibrary.RootSubmitData;
23 | import license.szca.com.licensekeylibrary.SHAUtil;
24 |
25 | import static license.szca.com.licenseapp.common.Constant.MSG_CHECK_LICENSE;
26 | import static license.szca.com.licenseapp.common.Constant.MSG_GET_LICENSE;
27 |
28 |
29 | /**
30 | * description 用Messenger(AIDL)通信的进程服务
31 | * Created by JD
32 | * on 2017/9/20.
33 | */
34 |
35 | public class BackService extends Service {
36 |
37 |
38 | private SHAUtil shaUtil;
39 | private CodeUtil codeUtil;
40 | private RSAUtil rsaUtil;
41 | private AESUtil aesUtil;
42 | private final String TAG = "BackService";
43 |
44 | @Override
45 | public void onCreate() {
46 | super.onCreate();
47 | shaUtil = new SHAUtil();
48 | rsaUtil = new RSAUtil();
49 | codeUtil = new CodeUtil();
50 | aesUtil = new AESUtil();
51 | rsaUtil.initPrivateAndPublicKey();
52 | }
53 |
54 | private class MessengerHandler extends Handler {
55 | @Override
56 | public void handleMessage(Message msg) {
57 | switch (msg.what) {
58 | //生成证书
59 | case MSG_GET_LICENSE:
60 | genLicense(msg);
61 | break;
62 | //校验数据
63 | case MSG_CHECK_LICENSE:
64 | checkData(msg);
65 | break;
66 |
67 | }
68 |
69 |
70 | }
71 | }
72 |
73 | /**
74 | * 生成证书,并连同RSA公钥发给客户端
75 | *
76 | * @param msg
77 | */
78 | private void genLicense(Message msg) {
79 | String clientData = msg.getData().getString("userData");
80 | byte[] sha1Data = shaUtil.encodeSHA1(clientData.getBytes());
81 | String licenseKey = codeUtil.hexData(sha1Data);
82 | //获取RSA的公钥
83 | byte[] rsaPublicKey = rsaUtil.getPublicKey();
84 | //把证书和公钥发给客户端:
85 | try {
86 | Messenger replyMessenger = msg.replyTo;
87 | Message replyMessage = new Message();
88 | Bundle bundle = new Bundle();
89 | bundle.putString("license", licenseKey);
90 | bundle.putByteArray("rsaPublicKey", rsaPublicKey);
91 | replyMessage.what = MSG_GET_LICENSE;
92 | replyMessage.setData(bundle);
93 | replyMessenger.send(replyMessage);
94 | } catch (RemoteException e) {
95 | e.printStackTrace();
96 | }
97 | }
98 |
99 | /**
100 | * 校验数据
101 | *
102 | * @param msg
103 | */
104 | private void checkData(Message msg) {
105 | String submitData = msg.getData().getString("submitData");
106 | Gson gson = new Gson();
107 | RootSubmitData rootSubmitData = gson.fromJson(submitData, RootSubmitData.class);
108 | byte[] aesKey = Hex.decode(rootSubmitData.getEncrptAESKey());
109 | byte[] encryptClientData = Hex.decode(rootSubmitData.getEncryptAESClientData());
110 | byte[] signData = Hex.decode(rootSubmitData.getSignData());
111 | byte[] rsaSignPublicKey = Hex.decode(rootSubmitData.getRsaSignPublicKey());
112 |
113 |
114 | //用RSA私钥解密出AES密钥
115 | byte[] aesKeyByte = rsaUtil.decryptWithPrivateKey(aesKey, rsaUtil.getPrivateKey());
116 | //用AES密钥解密出客户端数据
117 | byte[] decryptClientData = aesUtil.decryptData(encryptClientData, aesKeyByte);
118 | String result = new String(Hex.decode(decryptClientData));
119 | Log.d(TAG, result);
120 |
121 | if (isLicenseEqual(result) && isSignCorrect(result, signData, rsaSignPublicKey)) {
122 | replyResult(true, msg);
123 | } else {
124 | replyResult(false, msg);
125 | }
126 |
127 |
128 | }
129 |
130 | /**
131 | * 签名校验结果
132 | *
133 | * @param result
134 | * @param signData
135 | * @param rsaSignPublicKey
136 | * @return
137 | */
138 | private boolean isSignCorrect(String result, byte[] signData, byte[] rsaSignPublicKey) {
139 | return rsaUtil.verify(result.getBytes(), rsaSignPublicKey, signData);
140 | }
141 |
142 | /**
143 | * 返回结果给客户端
144 | *
145 | * @param result
146 | * @param msg
147 | */
148 | private void replyResult(boolean result, Message msg) {
149 | try {
150 | Messenger replyMessenger = msg.replyTo;
151 | Message replyMessage = new Message();
152 | Bundle bundle = new Bundle();
153 | bundle.putBoolean("success", result);
154 | replyMessage.what = MSG_CHECK_LICENSE;
155 | replyMessage.setData(bundle);
156 | replyMessenger.send(replyMessage);
157 | } catch (RemoteException e) {
158 | e.printStackTrace();
159 | }
160 | }
161 |
162 | /**
163 | * 校验客户端传过来的证书和服务端生成的证书是否一致
164 | *
165 | * @param result
166 | * @return
167 | */
168 | private boolean isLicenseEqual(String result) {
169 | Gson gson = new Gson();
170 | RootData rootData = gson.fromJson(result, RootData.class);
171 | String data = rootData.getUserName()
172 | + rootData.getUuid()
173 | + rootData.getApplicationId();
174 | String newLicense = codeUtil.hexData(
175 | shaUtil.encodeSHA1(data.getBytes())
176 | );
177 | //判断由username,uuid和applicationId拼接并哈希后的值与客户端传过来的证书是否一致
178 | if (newLicense.equals(rootData.getLicenseKey())) {
179 | Log.d(TAG, "校验成功");
180 | return true;
181 |
182 | } else {
183 | Log.d(TAG, "校验失败");
184 | return false;
185 | }
186 | }
187 |
188 |
189 | private Messenger mMessenger = new Messenger(new MessengerHandler());
190 |
191 | @Nullable
192 | @Override
193 | public IBinder onBind(Intent intent) {
194 | return mMessenger.getBinder();
195 | }
196 | }
197 |
--------------------------------------------------------------------------------
/licensekeylibrary/src/main/java/license/szca/com/licensekeylibrary/RSAUtil.java:
--------------------------------------------------------------------------------
1 | package license.szca.com.licensekeylibrary;
2 |
3 | import org.spongycastle.jce.provider.BouncyCastleProvider;
4 |
5 | import java.security.InvalidKeyException;
6 | import java.security.Key;
7 | import java.security.KeyFactory;
8 | import java.security.KeyPair;
9 | import java.security.KeyPairGenerator;
10 | import java.security.NoSuchAlgorithmException;
11 | import java.security.NoSuchProviderException;
12 | import java.security.PrivateKey;
13 | import java.security.PublicKey;
14 | import java.security.Security;
15 | import java.security.Signature;
16 | import java.security.SignatureException;
17 | import java.security.interfaces.RSAPrivateKey;
18 | import java.security.interfaces.RSAPublicKey;
19 | import java.security.spec.InvalidKeySpecException;
20 | import java.security.spec.PKCS8EncodedKeySpec;
21 | import java.security.spec.X509EncodedKeySpec;
22 | import java.util.HashMap;
23 | import java.util.Map;
24 |
25 | import javax.crypto.BadPaddingException;
26 | import javax.crypto.Cipher;
27 | import javax.crypto.IllegalBlockSizeException;
28 | import javax.crypto.NoSuchPaddingException;
29 |
30 | /**
31 | * description : RSA工具类
32 | * author : JDNew
33 | * on : 2017/9/17.
34 | */
35 |
36 | public class RSAUtil {
37 |
38 | static {
39 | //从位置1开始,添加新的提供者
40 | Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
41 | }
42 |
43 | private Map mKeyMap = new HashMap<>();
44 | private final String PUBLIC_KEY = "publicKey";
45 | private final String PRIVATE_KEY = "privateKey";
46 | private final String KEY_ALGORITHM = "RSA";
47 | private final String SIGN_ALGORITHM = "SHA1withRSA";
48 |
49 |
50 | /**
51 | * RSA私钥加密数据
52 | *
53 | * @param data 要加密的数据
54 | * @param privateKeyByte 二进制的私钥
55 | * @return 私钥加密后的数据
56 | */
57 | public byte[] encryptWithPrivateKey(byte[] data, byte[] privateKeyByte) {
58 | byte[] dataBytes = null;
59 | try {
60 | PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
61 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
62 | PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
63 |
64 | Cipher cipher = Cipher.getInstance("RSA", new BouncyCastleProvider());
65 | cipher.init(Cipher.ENCRYPT_MODE, privateKey);
66 | dataBytes = cipher.doFinal(data);
67 | } catch (NoSuchAlgorithmException e) {
68 | e.printStackTrace();
69 | } catch (NoSuchPaddingException e) {
70 | e.printStackTrace();
71 | } catch (BadPaddingException e) {
72 | e.printStackTrace();
73 | } catch (IllegalBlockSizeException e) {
74 | e.printStackTrace();
75 | } catch (InvalidKeyException e) {
76 | e.printStackTrace();
77 | } catch (InvalidKeySpecException e) {
78 | e.printStackTrace();
79 | }
80 |
81 | return dataBytes;
82 | }
83 |
84 |
85 | /**
86 | * RSA公钥加密数据
87 | *
88 | * @param data 要加密的数据
89 | * @param publicKeyByte 二进制的公钥
90 | * @return 公钥加密后的数据
91 | */
92 | public byte[] encryptWithPublicKey(byte[] data, byte[] publicKeyByte) {
93 | byte[] dataBytes = null;
94 | try {
95 | X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
96 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
97 | PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
98 |
99 | Cipher cipher = Cipher.getInstance("RSA", new BouncyCastleProvider());
100 | cipher.init(Cipher.ENCRYPT_MODE, publicKey);
101 | dataBytes = cipher.doFinal(data);
102 | } catch (NoSuchAlgorithmException e) {
103 | e.printStackTrace();
104 | } catch (NoSuchPaddingException e) {
105 | e.printStackTrace();
106 | } catch (BadPaddingException e) {
107 | e.printStackTrace();
108 | } catch (IllegalBlockSizeException e) {
109 | e.printStackTrace();
110 | } catch (InvalidKeyException e) {
111 | e.printStackTrace();
112 | } catch (InvalidKeySpecException e) {
113 | e.printStackTrace();
114 | }
115 |
116 | return dataBytes;
117 | }
118 |
119 |
120 | /**
121 | * RSA解密数据
122 | *
123 | * @param data 要解密的数据
124 | * @param publicKeyByte 二进制公钥
125 | * @return 解密后的数据
126 | */
127 | public byte[] decryptWithPublicKey(byte[] data, byte[] publicKeyByte) {
128 | byte[] dataBytes = null;
129 | try {
130 | X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
131 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
132 | PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
133 |
134 | Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm(), new BouncyCastleProvider());
135 | cipher.init(Cipher.DECRYPT_MODE, publicKey);
136 | dataBytes = cipher.doFinal(data);
137 | } catch (NoSuchAlgorithmException e) {
138 | e.printStackTrace();
139 | } catch (NoSuchPaddingException e) {
140 | e.printStackTrace();
141 | } catch (BadPaddingException e) {
142 | e.printStackTrace();
143 | } catch (IllegalBlockSizeException e) {
144 | e.printStackTrace();
145 | } catch (InvalidKeyException e) {
146 | e.printStackTrace();
147 | } catch (InvalidKeySpecException e) {
148 | e.printStackTrace();
149 | }
150 |
151 | return dataBytes;
152 | }
153 |
154 | /**
155 | * RSA解密数据
156 | *
157 | * @param data 要解密的数据
158 | * @param privateKeyByte 二进制私钥
159 | * @return 解密后的数据
160 | */
161 | public byte[] decryptWithPrivateKey(byte[] data, byte[] privateKeyByte) {
162 | byte[] dataBytes = null;
163 | try {
164 | PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
165 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
166 | PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
167 |
168 | Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm(), new BouncyCastleProvider());
169 | cipher.init(Cipher.DECRYPT_MODE, privateKey);
170 | dataBytes = cipher.doFinal(data);
171 | } catch (NoSuchAlgorithmException e) {
172 | e.printStackTrace();
173 | } catch (NoSuchPaddingException e) {
174 | e.printStackTrace();
175 | } catch (BadPaddingException e) {
176 | e.printStackTrace();
177 | } catch (IllegalBlockSizeException e) {
178 | e.printStackTrace();
179 | } catch (InvalidKeyException e) {
180 | e.printStackTrace();
181 | } catch (InvalidKeySpecException e) {
182 | e.printStackTrace();
183 | }
184 |
185 | return dataBytes;
186 | }
187 |
188 |
189 | /**
190 | * 初始化生成公钥和密钥
191 | *
192 | * @return
193 | */
194 | public Map initPrivateAndPublicKey() {
195 |
196 | try {
197 | KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "SC");
198 | keyPairGenerator.initialize(2048);
199 | //生成一个密钥对
200 | KeyPair keyPair = keyPairGenerator.generateKeyPair();
201 | RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
202 | RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
203 | mKeyMap.put(PUBLIC_KEY, publicKey);
204 | mKeyMap.put(PRIVATE_KEY, privateKey);
205 | // Log.d(TAG, "生成密钥对成功");
206 | } catch (NoSuchAlgorithmException e) {
207 | e.printStackTrace();
208 | } catch (NoSuchProviderException e) {
209 | e.printStackTrace();
210 | }
211 |
212 |
213 | return mKeyMap;
214 | }
215 |
216 | /**
217 | * 获取生成的密钥
218 | *
219 | * @return
220 | */
221 | public byte[] getPrivateKey() {
222 | return mKeyMap.get(PRIVATE_KEY).getEncoded();
223 | }
224 |
225 | /**
226 | * 获取生成的公钥
227 | *
228 | * @return
229 | */
230 | public byte[] getPublicKey() {
231 | return mKeyMap.get(PUBLIC_KEY).getEncoded();
232 | }
233 |
234 |
235 | /**
236 | * 用私钥签名
237 | *
238 | * @param data 要签名的数据
239 | * @param privateKeyByte 私钥
240 | * @return 已签名的数据
241 | */
242 | public byte[] signWithPrivateKey(byte[] data, byte[] privateKeyByte) {
243 |
244 | byte[] result = null;
245 | try {
246 | PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
247 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
248 | PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
249 | Signature signature = Signature.getInstance(SIGN_ALGORITHM);
250 | signature.initSign(privateKey);
251 | signature.update(data);
252 | result = signature.sign();
253 |
254 |
255 | } catch (NoSuchAlgorithmException e) {
256 | e.printStackTrace();
257 | } catch (InvalidKeySpecException e) {
258 | e.printStackTrace();
259 | } catch (InvalidKeyException e) {
260 | e.printStackTrace();
261 | } catch (SignatureException e) {
262 | e.printStackTrace();
263 | }
264 |
265 | return result;
266 | }
267 |
268 | /**
269 | * 校验签名
270 | *
271 | * @param data 要校验的数据
272 | * @param publicKeyByte 公钥
273 | * @param sign 签名
274 | * @return 校验结果(布尔值)
275 | */
276 | public boolean verify(byte[] data, byte[] publicKeyByte, byte[] sign) {
277 | boolean result = false;
278 | try {
279 | X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyByte);
280 | KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
281 | PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
282 | Signature signature = Signature.getInstance(SIGN_ALGORITHM);
283 | signature.initVerify(publicKey);
284 | signature.update(data);
285 | result = signature.verify(sign);
286 |
287 |
288 | } catch (NoSuchAlgorithmException e) {
289 | e.printStackTrace();
290 | } catch (InvalidKeySpecException e) {
291 | e.printStackTrace();
292 | } catch (InvalidKeyException e) {
293 | e.printStackTrace();
294 | } catch (SignatureException e) {
295 | e.printStackTrace();
296 | }
297 |
298 | return result;
299 | }
300 |
301 | }
302 |
--------------------------------------------------------------------------------