Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JCE Implementation of GmSSL Simultaneously Updating Document Description #31

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
9 changes: 5 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ lint/tmp/



/.idea/compiler.xml
/.idea/encodings.xml
/.idea/jarRepositories.xml
/.idea/misc.xml
/.idea/
/target/
/*.mpk
/*.txt
/*.pem
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ GmSSL-Java是采用JNI (Java Native Interface)方式实现的,也就是说所

GmSSL的项目组成主要包括C语言的本地代码、`src`目录下的Java类库代码、`examples`目录下面的例子代码。其中只有本地代码和`src`下面的Java类库代码会参与默认的编译,生成动态库和Jar包,而`examples`下的例子默认不编译也不进入Jar包。

GmSSL-Java提供一个包`org.gmssl`,其中包含如下密码算法类
GmSSL-Java提供两种实现,基于JCE的实现和基于java本身的基础实现。
JCE实现内容在包`org.gmssl.crypto`,可按照JCE调用方式完成各种算法功能,JCE调用可参考项目test目录下的JceTest类。因cipher属于Oracle java的受限“服务”,因此JCE调用前提必须使用[openJDK](https://jdk.java.net/archive/)。
基础实现内容在包`org.gmssl`,JDK来源不限制,其中包含如下密码算法类

* org.gmssl.Random
* org.gmssl.Sm3
Expand Down Expand Up @@ -57,7 +59,7 @@ GmSSL-Java提供一个包`org.gmssl`,其中包含如下密码算法类
## 编译和安装

### 编译安装GmSSL
GmSSL-Java依赖GmSSL项目,在编译前需要先在系统上编译、安装并测试通过GmSSL库及工具。请在https://github.com/guanzhi/GmSSL 项目上下载最新发布的GmSSL代码,并完成编译、测试和安装。
GmSSL-Java依赖GmSSL项目,在编译前需要先在系统上编译、安装并测试通过GmSSL库及工具。请在https://github.com/guanzhi/GmSSL 项目上下载同一版本的GmSSL代码,并完成编译、测试和安装。

### 通过Maven编译安装GmSSL-java

Expand All @@ -84,7 +86,7 @@ mvn clean install
最终会执行单元测试并在target目录下生成相应版本jar包。

## 使用
在其他项目中使用GmSSL-java,只需在pom.xml中添加如下依赖:
以上步骤操作完成后会在本地Maven仓库生成项目相应jar包,在其他项目中使用GmSSL-java,只需在pom.xml中添加如下依赖:
```xml
<dependency>
<groupId>com.gmssl</groupId>
Expand Down
119 changes: 70 additions & 49 deletions src/main/java/org/gmssl/NativeLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;

Expand All @@ -26,7 +28,9 @@ public class NativeLoader {
/* custom jni library prefix path relative to project resources */
private static final String RESOURCELIB_PREFIXPATH = "lib";

static final String GMSSLJNILIB_NAME="libgmssljni";
static final String GMSSLJNILIB_NAME = "libgmssljni";

private static final Map<String, Path> loadedLibraries = new HashMap<>();

private static final Properties PROPERTIES = new Properties();

Expand All @@ -44,64 +48,80 @@ public class NativeLoader {

/**
* load jni lib from resources path,the parameter does not contain the path and suffix.
* @param libaray libarayName
*
* @param library libraryName
*/
public synchronized static void load (String libaray){
String resourceLibPath = RESOURCELIB_PREFIXPATH + "/" + libaray + "." + libExtension();
public static void load(String library) {
if (loadedLibraries.containsKey(library)) {
return;
}
Path tempFile = null;
String resourceLibPath = RESOURCELIB_PREFIXPATH + "/" + library + "." + libExtension();
try (InputStream inputStream = NativeLoader.class.getClassLoader().getResourceAsStream(resourceLibPath)) {
if (null == inputStream) {
throw new GmSSLException("lib file not found in JAR: " + resourceLibPath);
}
Path tempFile = Files.createTempFile(libaray, "."+libExtension());
tempFile = Files.createTempFile(library, "." + libExtension());
tempFile.toFile().deleteOnExit();
Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING);
checkReferencedLib();
System.load(tempFile.toAbsolutePath().toString());
loadedLibraries.put(library, tempFile);
}catch (IOException e){
throw new GmSSLException("lib file not found:"+ e.getMessage());
}catch (UnsatisfiedLinkError e){
throw new GmSSLException("Failed to load native library:"+ e.getMessage());
} catch (Exception e) {
throw new GmSSLException("Unable to load lib from JAR");
throw new GmSSLException("Unable to load lib!");
}finally {
if (null != tempFile) {
tempFile.toFile().delete();
}
}
}

/**
* Get the operating system type.
*
* @return operating system name
*/
static String osType(){
String os="unknown";
String osName = System.getProperty("os.name").toLowerCase();
if(osName.startsWith("windows")){
os="win";
}
if(osName.startsWith("linux")){
if ("dalvik".equalsIgnoreCase(System.getProperty("java.vm.name"))) {
os = "android";
System.setProperty("jna.nounpack", "true");
} else {
os="linux";
}
static String osType() {
String os = "unknown";
String vmName = System.getProperty("java.vm.name");
if ("dalvik".equalsIgnoreCase(vmName) || "art".equalsIgnoreCase(vmName)) {
os = "android";
}
if(osName.startsWith("mac os x") || osName.startsWith("darwin")){
os="osx";
String osName = System.getProperty("os.name").toLowerCase();
if (osName.startsWith("windows")) {
os = "win";
} else if (osName.startsWith("linux")) {
os = "linux";
} else if (osName.startsWith("mac os x") || osName.startsWith("darwin")) {
os = "osx";
} else {
System.err.println("Unsupported OS: " + osName);
}
return os;
}

/**
* Get the library extension name based on the operating system type.
*
* @return extension name
*/
static String libExtension(){
String osType=osType();
String libExtension=null;
if("win".equals(osType)){
libExtension="dll";
}
if("osx".equals(osType)){
libExtension="dylib";
}
if("linux".equals(osType)){
libExtension="so";
static String libExtension() {
String osType = osType();
String libExtension = null;
switch (osType) {
case "win":
libExtension = "dll";
break;
case "osx":
libExtension = "dylib";
break;
case "linux":
case "android":
libExtension = "so";
break;
default:
throw new IllegalArgumentException("Unsupported OS type!");
}
return libExtension;
}
Expand All @@ -112,20 +132,21 @@ static String libExtension(){
* in order to correct the @rpath path issue. Alternatively, you can manually execute the command
* "install_name_tool -change @rpath/libgmssl.3.dylib /usr/local/lib/libgmssl.3.dylib xxx/lib/libgmssljni.dylib" to fix the library reference path issue.
* This has already been loaded and manual execution is unnecessary.
*
*/
private static void checkReferencedLib(){
if("osx".equals(osType())){
String macReferencedLib=PROPERTIES.getProperty("macReferencedLib");
Optional<String> optionalStr = Optional.ofNullable(macReferencedLib);
if(optionalStr.isPresent() && !optionalStr.get().isEmpty()){
File libFile = new File(macReferencedLib);
if(libFile.exists()){
System.load(macReferencedLib);
}
}

}
}
private static void checkReferencedLib() {
if ("osx".equals(osType())) {
String macReferencedLib = PROPERTIES.getProperty("macReferencedLib");
if (null != macReferencedLib) {
System.load(macReferencedLib);
Optional<String> optionalStr = Optional.ofNullable(macReferencedLib);
if (optionalStr.isPresent() && !optionalStr.get().isEmpty()) {
File libFile = new File(macReferencedLib);
if (libFile.exists()) {
System.load(macReferencedLib);
}
}
}
}
}

}
1 change: 0 additions & 1 deletion src/main/java/org/gmssl/Sm4.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public Sm4(byte[] key, boolean do_encrypt) {
}

public void encrypt(byte[] in, int in_offset, byte[] out, int out_offset) {

if (in == null
|| in_offset < 0
|| in_offset + this.BLOCK_SIZE <= 0
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/org/gmssl/crypto/CipherPaddingEnum.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2014-2024 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
package org.gmssl.crypto;

/**
* @author yongfeili
* @email [email protected]
* @date 2024/07/27
* @description
*
*/
public enum CipherPaddingEnum {
NoPadding,
ZeroPadding,
PKCS5Padding,
PKCS7Padding;
}
42 changes: 42 additions & 0 deletions src/main/java/org/gmssl/crypto/GmSSLProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2014-2024 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
package org.gmssl.crypto;

import java.security.Provider;

/**
* @author yongfeili
* @email [email protected]
* @date 2024/07/27
* @description
* GmSSL-Java currently provides functionality for random number generation, SM3 hash, SM3 message authentication code (HMAC-SM3),
* SM4 encryption (including block encryption and CBC/CTR/GCM encryption modes), ZUC encryption, SM2 encryption/signature, SM9 encryption/signature, and SM2 certificate parsing.
* These features cover the main application development scenarios for the current Chinese cryptographic algorithms.
*/
public class GmSSLProvider extends Provider {

public GmSSLProvider() {
super("GmSSL", "3.1.1", "GmSSL Provider");

put("SecureRandom.Random", "org.gmssl.crypto.Random");
put("Cipher.SM2", "org.gmssl.crypto.asymmetric.SM2Cipher");
put("KeyPairGenerator.SM2", "org.gmssl.crypto.asymmetric.SM2KeyPairGenerator");
put("Signature.SM2", "org.gmssl.crypto.asymmetric.SM2Signature");
put("MessageDigest.SM3", "org.gmssl.crypto.digest.SM3Digest");
put("Mac.SM3", "org.gmssl.crypto.digest.SM3Hmac");
put("SecretKeyFactory.SM3Pbkdf2", "org.gmssl.crypto.digest.SM3Pbkdf2");
put("Cipher.SM4", "org.gmssl.crypto.symmetric.SM4Cipher");
put("Cipher.SM9", "org.gmssl.crypto.asymmetric.SM9Cipher");
put("Signature.SM9", "org.gmssl.crypto.asymmetric.SM9Signature");
put("KeyPairGenerator.SM9", "org.gmssl.crypto.asymmetric.SM9KeyPairGeneratorSpi");
put("Cipher.ZUC", "org.gmssl.crypto.symmetric.ZucCipher");
}


}
51 changes: 51 additions & 0 deletions src/main/java/org/gmssl/crypto/PKCS7PaddingScheme.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2014-2024 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
package org.gmssl.crypto;

import java.util.Arrays;

/**
* @author yongfeili
* @email [email protected]
* @date 2024/07/27
* @description PKCS#7
*
*/
public class PKCS7PaddingScheme implements PaddingScheme{
@Override
public String getPaddingName() {
return "PKCS#7";
}

@Override
public byte[] pad(byte[] input, int blockSize) {
int paddingLength = blockSize - (input.length % blockSize);
byte[] padding = new byte[paddingLength];
Arrays.fill(padding, (byte) paddingLength);
byte[] result = new byte[input.length + padding.length];
System.arraycopy(input, 0, result, 0, input.length);
System.arraycopy(padding, 0, result, input.length, padding.length);
return result;
}

@Override
public byte[] unpad(byte[] input) {
int paddingSize = input[input.length - 1];
if (paddingSize <= 0 || paddingSize > input.length) {
throw new IllegalArgumentException("Invalid pkcs#7 padding!");
}
for (int i = input.length - paddingSize; i < input.length; i++) {
if (input[i] != paddingSize) {
throw new IllegalArgumentException("Invalid pkcs#7 padding!");
}
}
return Arrays.copyOfRange(input, 0, input.length - paddingSize);
}

}
40 changes: 40 additions & 0 deletions src/main/java/org/gmssl/crypto/PaddingScheme.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2014-2024 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
package org.gmssl.crypto;

/**
* @author yongfeili
* @email [email protected]
* @date 2024/07/27
* @description
*
*/
public interface PaddingScheme {

/**
* get padding name
* @return paddingName
*/
String getPaddingName();

/**
* Pad according to fixed block size
* @param input Data to be padded
* @param blockSize block size
* @return padded data
*/
byte[] pad(byte[] input, int blockSize);

/**
* Unpad according to fixed block size
* @param input Data to be unpadded
* @return unpadded data
*/
byte[] unpad(byte[] input);
}
Loading
Loading