毫无疑问用的是Jpype,因为百度一搜都是它。
github:https://github.com/jpype-project/jpype 官方文档:https://jpype.readthedocs.io/en/latest/
安装:pip install JPype1
被调用的Java代码
RSAUtils.java
package com.commonsdk.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Base64;
import java.math.BigInteger;
import java.util.UUID;
public class RSAUtils {
private int keySize;
private String publicKey = "919b6b41f2814f25b5e5fb7c64b03d67602dc07001e5d42aff525c743fdf8434a8b751a7849d5dafb3c3cda4309d739bbb86702214c110a4a431df6f3b8374fd";
private String temp = "1f5cec6336a772cadf5e887eb1c9fea2675393c0986796f7628a72157b02643a9968518ee54f8171fcb074aa4bd75becc2284028c59c3a8a900d976760823105017beae3a3a1a31be16a18c0892fc1c9e05657ff16ad9c9e7888a6ce9a6fadde73ba4da0ec87a84267ed518da60978dbab3b97641c0f80f3385bf38873d35565";
public RSAUtils(int i) {
this.keySize = i;
}
public BigInteger[] genKeys() throws Throwable {
SecureRandom secureRandom = new SecureRandom();
return genKeys(BigInteger.probablePrime((this.keySize / 2) - 1, secureRandom), BigInteger.probablePrime((this.keySize / 2) - 1, secureRandom), BigInteger.probablePrime(this.keySize / 2, secureRandom));
}
public String getKey(String valueOf) {
String uuid = UUID.randomUUID().toString();
String substring = valueOf.substring(valueOf.length() - 6, valueOf.length());
String substring2 = uuid.substring(0, 10);
return substring + substring2;
}
public BigInteger[] genKeys(BigInteger bigInteger, BigInteger bigInteger2, BigInteger bigInteger3) throws Throwable {
if (bigInteger3.compareTo(BigInteger.ONE) > 0) {
BigInteger[] bigIntegerArr = new BigInteger[3];
BigInteger multiply = bigInteger.multiply(bigInteger2);
BigInteger add = multiply.subtract(bigInteger).subtract(bigInteger2).add(BigInteger.ONE);
if (bigInteger3.compareTo(add) >= 0) {
throw new Throwable("e must be smaller than (p-1)*(q-1)");
} else if (add.gcd(bigInteger3).compareTo(BigInteger.ONE) == 0) {
BigInteger modInverse = bigInteger3.modInverse(add);
bigIntegerArr[0] = bigInteger3;
bigIntegerArr[1] = modInverse;
bigIntegerArr[2] = multiply;
return bigIntegerArr;
} else {
throw new Throwable("e must be coprime with (p-1)*(q-1)");
}
} else {
throw new Throwable("e must be larger than 1");
}
}
public String encode(String str) throws Throwable {
DataOutputStream dataOutputStream;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
dataOutputStream = new DataOutputStream(byteArrayOutputStream);
byte[] bArr = str.getBytes();
BigInteger bigInteger = new BigInteger(this.publicKey, 16);
BigInteger bigInteger2 = new BigInteger(this.temp, 16);
try {
try {
int i = this.keySize / 8;
int i2 = i - 11;
int i3 = 0;
while (bArr.length > i3) {
int min = Math.min(bArr.length - i3, i2);
byte[] encodeBlock = encodeBlock(bArr, i3, min, bigInteger, bigInteger2, i);
dataOutputStream.writeInt(encodeBlock.length);
dataOutputStream.write(encodeBlock);
i3 += min;
}
} catch (Exception e) {
e.printStackTrace();
}
dataOutputStream.close();
byte[] result = byteArrayOutputStream.toByteArray();
return Base64.getEncoder().encodeToString(result);
} catch (Throwable th) {
dataOutputStream.close();
throw th;
}
}
public byte[] encodeBlock(byte[] bArr, int i, int i2, BigInteger bigInteger, BigInteger bigInteger2, int i3) throws Throwable {
try {
if (!(bArr.length == i2 && i == 0)) {
byte[] bArr2 = new byte[i2];
System.arraycopy(bArr, i, bArr2, 0, i2);
bArr = bArr2;
}
BigInteger bigInteger3 = new BigInteger(paddingBlock(bArr, i3));
if (bigInteger3.compareTo(bigInteger2) <= 0) {
return bigInteger3.modPow(bigInteger, bigInteger2).toByteArray();
}
throw new Throwable("the message must be smaller than the modulue");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private byte[] paddingBlock(byte[] bArr, int i) throws Throwable {
if (bArr.length <= i - 1) {
try {
byte[] bArr2 = new byte[i];
bArr2[0] = 1;
int length = bArr.length;
bArr2[1] = (byte) (length >> 24);
bArr2[2] = (byte) (length >> 16);
bArr2[3] = (byte) (length >> 8);
bArr2[4] = (byte) length;
System.arraycopy(bArr, 0, bArr2, i - length, length);
return bArr2;
} catch (Exception e) {
e.printStackTrace();
return null;
}
} else {
throw new Throwable("Message too large");
}
}
public byte[] decode(byte[] bArr) throws Throwable {
DataInputStream dataInputStream = new DataInputStream(new ByteArrayInputStream(bArr));
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
BigInteger bigInteger = new BigInteger(this.publicKey, 16);
BigInteger bigInteger2 = new BigInteger(this.temp, 16);
while (dataInputStream.available() > 0) {
byte[] bArr2 = new byte[dataInputStream.readInt()];
dataInputStream.readFully(bArr2);
byteArrayOutputStream.write(decodeBlock(bArr2, bigInteger, bigInteger2));
}
dataInputStream.close();
byteArrayOutputStream.close();
return byteArrayOutputStream.toByteArray();
}
public byte[] decodeBlock(byte[] bArr, BigInteger bigInteger, BigInteger bigInteger2) throws Throwable {
return recoveryPaddingBlock(new BigInteger(bArr).modPow(bigInteger, bigInteger2).toByteArray());
}
private byte[] recoveryPaddingBlock(byte[] bArr) throws Throwable {
if (bArr[0] == 1) {
int i = ((bArr[1] & 255) << 24) + ((bArr[2] & 255) << 16) + ((bArr[3] & 255) << 8) + (bArr[4] & 255);
byte[] bArr2 = new byte[i];
System.arraycopy(bArr, bArr.length - i, bArr2, 0, i);
return bArr2;
}
throw new Throwable("Not RSA Block");
}
}
我的需求就一个文件,也没有什么依赖。所以调用应该没什么问题。
打包Jar包
目录结构: com\commonsdk\utils\RSAUtils.java
先生成class文件(需要运行在java代码同目录下) javac -encoding utf-8 RSAUtils.java 删除java代码文件,保留class文件
然后返回到com同级目录运行,就能生成RSAUtils.jar文件 jar -cvf RSAUtils.jar com
调用jar包
import jpype
import time
def get_rsa_sign():
jvmPath = jpype.getDefaultJVMPath()
jpype.startJVM(jvmPath, "-ea", "-Djava.class.path=RSAUtils1.jar")
JDClass = jpype.JClass("com.commonsdk.utils.RSAUtils")
jd = JDClass(1024)
key = str(jd.getKey(str(int(time.time()))))
print(key)
signature = str(jd.encode(key))
jpype.shutdownJVM()
return signature
if __name__ == '__main__':
print("rsa 签名结果:",get_rsa_sign())
因为java代码没什么依赖,所以也没遇到什么坑,试了试就过了
aardio调用java
aardio应该是需要32位的java,因为即使设置了环境变量,依然会自动下载java。但是代码设置的java下载地址已经失效了,抓个包看到地址是:https://mirrors.tuna.tsinghua.edu.cn/AdoptOpenJDK/8/jre/x32/windows/OpenJDK8U-jre_x86-32_windows_hotspot_8u312b07.zip,
去掉后面的文件名访问链接,发现只是版本变化了而已,搜一下aardio的源码,改一下地址和路径即可
调用jar包的代码大致和Python的一样,都是使用的jvm虚拟机
import console;
import java;
var jvm = java();
jvm.addClassLoaderUrl("D:\jar");
RSAUtils = jvm.import( "com.commonsdk.utils.RSAUtils");
var rsa = RSAUtils(1024);
var String = jvm.import( "java.lang.String");
var t = tostring(tonumber(time()));
var key = rsa.getKey(t);
console.log("key: ", key);
console.log("signature: ", rsa.encode(key))
console.pause();
|