正确使用 Aspose.Diagram for Java
最近在鼓捣java 如何生成visio图表,苦于没有API,找到了aspose这个神器,下载试用版本之后,发现最多只能生成10个元素,而且有水印。下面尝试如何去掉水印与元素限制。
本文章所涉及的软件均可从网上获取,但是只能用于学习之用,不能用于商业目的,正版的话请前往 aspose下载。
首先本次需要用到的软件:
JByteMod-Beta-1.8.2.zip
aspose-diagram-20.1-jdk16.jar
jboss-javassist-javassist.zip
第一步:使用JByteMod打开aspose-diagram-20.1-jdk16.jar,找到反编译之后找到License类,找到关键的设置License方法,如下:
public void setLicense(final InputStream inputStream) throws Exception { Document parse = null; if (inputStream != null) { try { parse = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream); } catch (Exception ex) { throw new DiagramException("Error when parse license stream."); } } this.a(parse); }
可以看到这是从某个配置文件里面输入一些关键的鉴权信息,那么配置文件里面应该有些什么东西呢,接着看:
void a(final Element element) throws Exception { try { int n = 0; final Node item = element.getElementsByTagName("Data").item(0); final Node item2 = element.getElementsByTagName("Signature").item(0); if (item != null && item2 != null) { final Node a = afl.a(item.getChildNodes(), "Products"); final NodeList list = (a != null) ? a.getChildNodes() : null; if (list != null) { this.b = new String[list.getLength()]; for (int i = 0; i < list.getLength(); ++i) { this.b[i] = a(a(list.item(i).getLastChild())); if (this.b[i].startsWith("Conholdate.")) { n = 1; } } } a(item, item2, n); final Node a2 = afl.a(item.getChildNodes(), "EditionType"); if (a2 != null) { this.c = e(a(a2.getLastChild())); } final Node a3 = afl.a(item.getChildNodes(), "SerialNumber"); if (a3 != null) { this.d = a(a3.getLastChild()); } else { this.d = ""; } final Node a4 = afl.a(item.getChildNodes(), "SubscriptionExpiry"); if (a4 != null) { this.e = b(a4.getLastChild()); } final Node a5 = afl.a(item.getChildNodes(), "LicenseExpiry"); if (a5 != null) { this.f = b(a5.getLastChild()); } final Node a6 = afl.a(item.getChildNodes(), "OemPublicKeyToken"); if (this.g != null) { this.g = a(a6.getLastChild()); } else { this.g = ""; } } } catch (DiagramException ex) { throw ex; } catch (Exception ex2) { throw new DiagramException("The license is invalid. "); } }
通过上面的节点解析代码看的不是很全,再继续看:
private static void a(final Node node, final Node node2, final int n) throws Exception { final String s = (node != null) ? afl.a(node) : ""; String replaceAll; if (s.equals("<Data />")) { replaceAll = "<Data></Data>"; } else { replaceAll = s.replaceAll("&", "&"); } try { final KeyFactory instance = KeyFactory.getInstance("RSA"); String i = License.i; if (n == 1) { i = "qKFqqhFovZvEYCHeD3N8Oy+AuxrOA8cVvIl4u4qIBMQlzejGyXkiTUjoryuzlhlS2bG80FGmFsH+wUKbYiEkW/4zseZCV/Ej/usbu6yHACQKO/SCy3pYw68Pcv901pvywUnoaYCI2ccCG29+XM+FwpFQuiPb2H7YbI/++SQs6Hk="; } final PublicKey generatePublic = instance.generatePublic(new RSAPublicKeySpec(new BigInteger(1, bf.a(i, "UTF-8")), new BigInteger(1, bf.a("AQAB", "UTF-8")))); final byte[] bytes = replaceAll.getBytes("UTF-16LE"); final byte[] a = bf.a((node2 != null) ? node2.getLastChild().getNodeValue() : "", "UTF-8"); final Signature instance2 = Signature.getInstance("SHA1withRSA"); instance2.initVerify(generatePublic); instance2.update(bytes); if (!instance2.verify(a)) { final PublicKey generatePublic2 = instance.generatePublic(new RSAPublicKeySpec(new BigInteger(1, bf.a("3ki45T6C4lt12J5MbKfrADBCZcE8OTefdngc9IDKg+lzCGYLuxJFDt16awhJFnA23sX+kQ4/eZQ5pNAYjc+ZJ0+pWwvQR4h8GJ3eWvecdFs7KSWwNmFXZCSN+sbrxwEjzzns1kIHuLNf5r+Zaggns+8rqXR19RSJBOcuFqVipIHv56lF53Hc+hx+y9URIaadO1W8dkTqgwExyfjnbDOaCBEH0CqUL1YIICS/wIUTEKhM0ZlwEcIcHl8XTHLVx96DMX4bbVajj78L4KzevQc442DX28KGDJTveEB1pSKWsr0d4FTx7wKS36RBnWv5lwsRErtTZb5ciVIG1iIJrp87VQ==", "UTF-8")), new BigInteger(1, bf.a("AQAB", "UTF-8")))); final Signature instance3 = Signature.getInstance("SHA256withRSA"); instance3.initVerify(generatePublic2); instance3.update(bytes); if (!instance3.verify(a)) { throw new DiagramException("The signature is invalid."); } } } catch (Exception ex) { throw new DiagramException("License signature reading error or signature is invalid."); } }
结合两段代码,重点在于<Data>结构体,配置文件的大致格式,解析的配置文件如下,这里我们新建一个license.xml,复制以下内容。
<License>
<Data>
<Products>
<Product>Aspose.Diagram for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>---</SerialNumber>
</Data>
<Signature>---</Signature>
</License>
同时,查看解析的代码,它是采用的RSA加密验证license合法性,我们修改字节码,把这个方法屏蔽掉应该就可以。这里需要使用到javassist 了。新建java工程,新建类,代码如下:
public static void changeMethod() throws Exception { ClassPool.getDefault().insertClassPath( "E:/aspose-crack/aspose-diagram-20.1-jdk16.jar"); CtClass ctclass = ClassPool.getDefault() .getCtClass("com.aspose.diagram.License"); CtMethod[] ms = ctclass.getDeclaredMethods(); for (CtMethod c : ms) { System.out.println(c.getName()); CtClass[] ps = c.getParameterTypes(); for (CtClass cx : ps) { System.out.println("\t" + cx.getName()); } if (c.getName().equals("a") && ps.length == 3 && ps[0].getName().equals("org.w3c.dom.Node") && ps[1].getName().equals("org.w3c.dom.Node")) { System.out.println("find it!"); c.insertBefore("{return;}"); } } ctclass.writeFile("E:/aspose-crack/"); }
其中,具体的jar包输入路径与最终的class文件输出路径可以自定义。
然后使用压缩文件打开 aspose-diagram-20.1-jdk16.jar,替换生成的License.class文件,然后把META-INF下的签名文件全部删掉。参考下面代码就能愉快使用了。
public static boolean getLicense() throws Exception { boolean result = false; try { InputStream is = new FileInputStream(new File("License.xml文件路径")); License license= new License(); license.setLicense(is); result = true; is.close(); } catch (Exception e) { e.printStackTrace(); throw e; } return result; }
在准备绘制visio之前,调用一次getLicense()方法就可以去掉水印与元素个数的限制了。
再次强调,仅供学习使用。
github参考资料(github是个好网站):