├── .gitattributes ├── .gitignore ├── README.md ├── pom.xml └── src ├── burp ├── BurpExtender.java └── Parameter.java └── custom ├── CAESOperator.java ├── CAESOperator_AES_256.java ├── CBase64.java ├── CGUI.java ├── CMD5.java ├── CMapSort.java ├── CRecalculater.java ├── CSHA1.java ├── CString2Other.java └── CUnicodeDecoder.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | /target/ 49 | *.class 50 | .fatjar 51 | *.class 52 | bin/ 53 | .classpath 54 | .project 55 | /.settings/ 56 | /.idea/ 57 | 58 | ReSign.iml 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Resign v2.0# 2 | 3 | ## Description ## 4 | 5 | A burp extender that recalculate signature value automatically after you modified request parameter value.but you need to know the signature algorithm detail and configure at GUI. 6 | 7 | 一个可以在你修改请求参数值后,自动从新计算sign的burp插件。但是前提是你需要知道具体的算法细节,并且在插件的GUI中配置。 8 | 9 | ![](http://i.imgur.com/4YQR4IT.png) 10 | 11 | ## Background ## 12 | 13 | More and more mobile developers begin to use the signature algorithm to improve the security of App. when we test the App generated requests, always need to recalculate the sign value and update it again and again to make the request pass the server check. 14 | 15 | 越来越多的移动开发者在App的请求中加入签名来提高安全性。当我们测试App生成的请求接口,总需要一次又一次地从新计算sign并更新sign值才能保证请求通过服务端的校验。 16 | 17 | ## Requirement ## 18 | 19 | Java 1.8 20 | 21 | ## Usage ## 22 | 23 | 1. download this extender from [here](https://github.com/bit4woo/GUI_Burp_Extender_ReSign/releases "here") , and add to burp. 24 | 25 | 26 | 2. Use "Send to ReSign"![](http://i.imgur.com/kbThsZJ.png) 27 | 28 | 29 | 3. Chose take effect for. you can control which components take effect for by select or cancel the select on the Window top 30 | 31 | 32 | 4. Config 33 | 34 | 35 | first, which parameters will take part in and how to sort. remove the ones that don't need, move up and down or click table header to sort. 36 | 37 | 第一,决定哪些参数要参与签名,将不需要的参数移除;决定参数如何排序,可以通过“move up”和“move down”来自定义排序,也可以通过点击表头来实现升序降序排序。 38 | 39 | second, which parameter is sign. select the sign parameter and click "Mark As Sign". 40 | 41 | 第二,标记出签名字段,选择签名的字段,并点击“Mark As Sign”将其标记为sign字段。 42 | 43 | thirdly, input the secrect key(md5 salt).if secret key will be use as a normal parameter, it should be like "key=secretkey" --a key value format;if the secret key will be append to the end when parameters have been oredered and combined, should be like "&key=secretkey"(there is a connector string usually, & is the connector string in this example.) 44 | 45 | 第三,输入secret key(或者md5盐)。如果这个key将被当作和普通参数一样对待,那么它的格式应该是键值对的形式。如果key是在参数排好序、拼接好后附加在末尾,那么它应该包含一个连接符(如果需要的话)比如“&key=secretkey”。 46 | 47 | finally, chose how to combine parameters. 48 | 49 | 最后,决定怎样拼接参数。是否值使用value,不需要“key=”; 拼接是否需要使用连接字符,连接字符是什么(一般是&) 50 | 51 | **Caution:you can always click "show final string" to see whether the result string is you want.** 52 | 53 | **重要提示:如果对选项理解不清晰,你可以随时点击“show final string”看看拼接的效果。** 54 | 55 | 56 | 5.Use timestamp in parameter 57 | 58 | ![](http://i.imgur.com/r0NDPv1.jpg) 59 | 60 | 61 | ## ReSign v2.0 Change log ## 62 | 63 | 64 | - support SHA1. 65 | - support custome order. 66 | - support parameter combine control: chose whether only use value; specify the connector string. 67 | - adjust the scope policy that the extender config take effect:this extender is main for single request(like other burp origin components),that means you need to config again for each request. if the config are same in same domain, you don't need to do that again. 68 | 69 | - 增加SHA1算法支持。 70 | - 增加自定义排序支持。 71 | - 增加字符拼接控制:是否只使用value,指定拼接连接符。 72 | - 调整插件生效范围策略:主要针对单个请求(就像burp的原生组件一样),也就是说对于每个单独的请求都需从新配置。但是如果同域下其他接口的签名参数和方法完全一样,则可以不用重新配置。 73 | 74 | 75 | ## ReSign v2.1 Change log ## 76 | 77 | - fix remove issue after sort. 78 | - support remove multiple rows. 79 | - fix URL encode issue in "Send to ReSign" menu. 80 | 81 | - 修复排序后删除异常的问题。 82 | - 增加支持多行删除。 83 | - 修复“发送到 Resign”中的URL编码问题。 84 | 85 | 86 | ## ReSign v2.2 Change log ## 87 | 88 | - Support timestamp in parameter value ,basing on current system time. 89 | - Optimized log format. 90 | 91 | 92 | - 支持时间戳形式的参数值,通过获取当前系统时间实现。 93 | - 优化了log输出格式。 94 | 95 | 96 | ## issue and contribute ## 97 | 98 | any issue and contribute are welcomed。 99 | 100 | 欢迎提issue,提bug。 -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | com.bit4woo.burp 6 | ReSign 7 | 2.3 8 | 9 | src 10 | 11 | 12 | maven-compiler-plugin 13 | 3.8.1 14 | 15 | 1.8 16 | 1.8 17 | UTF-8 18 | 19 | 20 | 21 | 22 | maven-assembly-plugin 23 | 3.3.0 24 | 25 | 26 | jar-with-dependencies 27 | 28 | 29 | 30 | 31 | true 32 | 33 | 34 | 35 | 36 | 37 | 38 | make-assembly 39 | package 40 | 41 | single 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | com.alibaba 54 | fastjson 55 | 2.0.18 56 | 57 | 58 | 59 | 60 | 61 | net.portswigger.burp.extender 62 | burp-extender-api 63 | 2.3 64 | 65 | 66 | 67 | com.github.bit4woo 68 | burp-api-common 69 | 0.1.4 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.awt.Component; 4 | import java.awt.event.ActionEvent; 5 | import java.awt.event.ActionListener; 6 | import java.io.PrintWriter; 7 | import java.net.URLDecoder; 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.LinkedHashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import javax.swing.JMenuItem; 15 | import javax.swing.SortOrder; 16 | import javax.swing.SwingUtilities; 17 | import javax.swing.table.DefaultTableModel; 18 | 19 | import custom.CGUI; 20 | 21 | 22 | public class BurpExtender implements IBurpExtender, IHttpListener, ITab, IContextMenuFactory 23 | { 24 | private IBurpExtenderCallbacks callbacks; 25 | public static IExtensionHelpers helpers; 26 | private PrintWriter stdout;//现在这里定义变量,再在registerExtenderCallbacks函数中实例化,如果都在函数中就只是局部变量,不能在这实例化,因为要用到其他参数。 27 | public String extenderName = "Resign v2.3 by bit4woo"; 28 | 29 | 30 | public String secretKey = null; 31 | public int sortedColumn; 32 | public SortOrder sortedMethod; 33 | public String howDealKey = ""; //sameAsPara or appendToEnd 34 | 35 | private CGUI GUI; 36 | public static IHttpRequestResponse currentMessage; 37 | public static List paras; 38 | public static IParameter signPara; 39 | 40 | 41 | // implement IBurpExtender 42 | @Override 43 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) 44 | {//当加载插件的时候,会调用下面的方法。 45 | stdout = new PrintWriter(callbacks.getStdout(), true); 46 | //PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true); 这种写法是定义变量和实例化,这里的变量就是新的变量而不是之前class中的全局变量了。 47 | stdout.println(extenderName+" https://github.com/bit4woo\r\n"); 48 | //System.out.println("test"); 不会输出到burp的 49 | this.callbacks = callbacks; 50 | helpers = callbacks.getHelpers(); 51 | callbacks.setExtensionName(extenderName); //插件名称 52 | callbacks.registerHttpListener(this); //如果没有注册,下面的processHttpMessage方法是不会生效的。处理请求和响应包的插件,这个应该是必要的 53 | callbacks.registerContextMenuFactory(this); 54 | GUI = new CGUI(); 55 | addMenuTab(); 56 | } 57 | 58 | @Override 59 | public void processHttpMessage(int toolFlag,boolean messageIsRequest,IHttpRequestResponse messageInfo) 60 | { 61 | if (toolFlag == (toolFlag&GUI.checkEnabledFor())){ //不同的toolflag代表了不同的burp组件 https://portswigger.net/burp/extender/api/constant-values.html#burp.IBurpExtenderCallbacks 62 | if (messageIsRequest){ //对请求包进行处理 63 | stdout.println("Origin Request:"); 64 | stdout.println(new String(messageInfo.getRequest())); 65 | stdout.println("\r\n"); 66 | HelperPlus getter = new HelperPlus(helpers); 67 | String host = getter.getHost(messageInfo); 68 | getSignPara(); 69 | 70 | //*******************recalculate sign**************************// 71 | if (host.equals(GUI.getHostFromUI()) && signPara.getType() !=-1){//检查图形面板上的各种参数,都齐备了才进行。 72 | String timeStamp = Long.toString(System.currentTimeMillis()); 73 | 74 | String str = GUI.combineString(GUI.getParaMapFromTable(),GUI.getOnlyValueConfig(),GUI.getParaConnector()); 75 | str = str.replace("", timeStamp); 76 | String newSign = GUI.calcSign(str); 77 | 78 | //更新参数 79 | IParameter newSignPara = new Parameter(signPara.getName(),newSign,signPara.getType()); 80 | updateMessage(true,messageInfo,newSignPara); 81 | 82 | IParameter timePara = GUI.getParaThatUseTimeStamp(); 83 | 84 | IParameter newTimePara = new Parameter(timePara.getName(),timeStamp,timePara.getType()); 85 | updateMessage(true,messageInfo,newTimePara); 86 | 87 | stdout.println("Changed Request:"); 88 | stdout.println(new String(messageInfo.getRequest())); 89 | stdout.print("\r\n"); 90 | } 91 | } 92 | } 93 | } 94 | 95 | /** 96 | * 更新数据包。要替换的数据包可能时header头--自行实现的 97 | * 98 | */ 99 | public void updateMessage(boolean messageIsRequest,IHttpRequestResponse messageInfo,IParameter para) { 100 | HelperPlus getter = new HelperPlus(helpers); 101 | 102 | if(para.getType() == IParameter.PARAM_JSON) { 103 | List headers = getter.getHeaderList(messageIsRequest,messageInfo); 104 | 105 | byte[] body = HelperPlus.getBody(messageIsRequest, messageInfo); 106 | 107 | String oldchar = getter.getParameterByKey(messageInfo, para.getName()).getValue(); 108 | String newBody = new String(body).replace(oldchar, para.getValue()); 109 | 110 | byte[] bodyByte = newBody.getBytes(); 111 | byte[] new_Request = helpers.buildHttpMessage(headers, bodyByte); //关键方法 112 | messageInfo.setRequest(new_Request);//设置最终新的请求包 113 | }else if(para.getType() == Parameter.PARAM_Header) { 114 | List headers = getter.getHeaderList(true,messageInfo); 115 | byte[] body = HelperPlus.getBody(true, messageInfo); 116 | 117 | for (String header:headers) { 118 | if (header.startsWith(para.getName()+":")) { 119 | headers.remove(header); 120 | headers.add(para.getName()+": "+para.getValue()); 121 | break; 122 | } 123 | } 124 | 125 | byte[] new_Request = helpers.buildHttpMessage(headers, body); //关键方法 126 | messageInfo.setRequest(new_Request);//设置最终新的请求包 127 | }else { 128 | byte[] new_Request = helpers.updateParameter(messageInfo.getRequest(), para); //构造新的请求包,这里是方法一updateParameter 129 | messageInfo.setRequest(new_Request);//设置最终新的请求包 130 | } 131 | } 132 | 133 | public void getSignPara(){ 134 | String signParaName = GUI.textFieldSign.getText(); 135 | List paras = getParasAndHeaders(currentMessage); 136 | for(IParameter para:paras){ 137 | if (para.getName().equals(signParaName)) { 138 | signPara = para; 139 | } 140 | } 141 | } 142 | 143 | 144 | /** 145 | * 返回各种可能用于签名的参数、包含header。 146 | * @param messageInfo 147 | * @return 148 | */ 149 | public List getParasAndHeaders(IHttpRequestResponse messageInfo){ 150 | 151 | Getter getter = new Getter(BurpExtender.helpers); 152 | 153 | List paras = getter.getParas(messageInfo); 154 | LinkedHashMap headers = getter.getHeaderMap(true,messageInfo); 155 | for (String key:headers.keySet()) { 156 | Parameter para = new Parameter(key,headers.get(key),Parameter.PARAM_Header); 157 | paras.add(para); 158 | } 159 | return paras; 160 | } 161 | 162 | 163 | 164 | //以下是各种burp必须的方法 --start 165 | public void addMenuTab() 166 | { 167 | SwingUtilities.invokeLater(new Runnable() 168 | { 169 | public void run() 170 | { 171 | BurpExtender.this.callbacks.addSuiteTab(BurpExtender.this); 172 | //这里的BurpExtender.this实质是指ITab对象,也就是getUiComponent()中的contentPane.这个参数由CGUI()函数初始化。 173 | //如果这里报java.lang.NullPointerException: Component cannot be null 错误,需要排查contentPane的初始化是否正确。 174 | } 175 | }); 176 | } 177 | 178 | 179 | //ITab必须实现的两个方法 180 | @Override 181 | public String getTabCaption() { 182 | return ("ReSign"); 183 | } 184 | @Override 185 | public Component getUiComponent() { 186 | return GUI.getContentPane(); 187 | } 188 | //ITab必须实现的两个方法 189 | 190 | 191 | //IContextMenuFactory 必须实现的方法 192 | @Override 193 | public List createMenuItems(IContextMenuInvocation invocation) 194 | { //需要在前面注册!!callbacks.registerContextMenuFactory(this); 195 | IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 196 | List list = new ArrayList(); 197 | if((messages != null) && (messages.length > 0)) 198 | { 199 | //this.callbacks.printOutput("Messages in array: " + messages.length); 200 | 201 | currentMessage = messages[0]; 202 | JMenuItem menuItem = new JMenuItem("Send to ReSign"); 203 | menuItem.addActionListener(new ActionListener() 204 | { 205 | public void actionPerformed(ActionEvent e) 206 | { 207 | try 208 | { 209 | GUI.textFieldDomain.setText(currentMessage.getHttpService().getHost()); 210 | 211 | DefaultTableModel tableModel = (DefaultTableModel) GUI.table.getModel(); 212 | tableModel.setRowCount(0);//为了清空之前的数据 213 | 214 | List paras = getParasAndHeaders(currentMessage); 215 | for(IParameter para:paras){ 216 | tableModel.addRow(new Object[]{URLDecoder.decode(para.getName()),URLDecoder.decode(para.getValue()),para.getType()}); 217 | } 218 | } 219 | catch (Exception e1) 220 | { 221 | BurpExtender.this.callbacks.printError(e1.getMessage()); 222 | } 223 | } 224 | }); 225 | list.add(menuItem); 226 | } 227 | return list; 228 | } 229 | //各种burp必须的方法 --end 230 | 231 | } -------------------------------------------------------------------------------- /src/burp/Parameter.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | public class Parameter implements IParameter{ 4 | String name; 5 | String value; 6 | byte type; 7 | 8 | 9 | public static byte PARAM_Header = 7; 10 | 11 | public Parameter(String name,String vaule,byte type) { 12 | this.name = name; 13 | this.value = vaule; 14 | this.type = type; 15 | } 16 | @Override 17 | public byte getType() { 18 | return type; 19 | } 20 | 21 | @Override 22 | public String getName() { 23 | return name; 24 | } 25 | 26 | @Override 27 | public String getValue() { 28 | return value; 29 | } 30 | 31 | @Override 32 | public int getNameStart() { 33 | // TODO Auto-generated method stub 34 | return 0; 35 | } 36 | @Override 37 | public int getNameEnd() { 38 | // TODO Auto-generated method stub 39 | return 0; 40 | } 41 | @Override 42 | public int getValueStart() { 43 | // TODO Auto-generated method stub 44 | return 0; 45 | } 46 | @Override 47 | public int getValueEnd() { 48 | // TODO Auto-generated method stub 49 | return 0; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/custom/CAESOperator.java: -------------------------------------------------------------------------------- 1 | package custom; 2 | 3 | import java.util.Scanner; 4 | 5 | import javax.crypto.Cipher; 6 | import javax.crypto.spec.IvParameterSpec; 7 | import javax.crypto.spec.SecretKeySpec; 8 | 9 | import custom.CBase64; 10 | 11 | /**AES 是一种可逆加密算法,对用户的敏感信息加密处理 12 | * 对原始数据进行AES加密后,在进行Base64编码转化; 13 | */ 14 | public class CAESOperator { 15 | /* 16 | * 加密用的Key 可以用26个字母和数字组成 17 | * 此处使用AES-128-CBC加密模式,key需要为16位。 18 | */ 19 | private String sKey="@tony@2015ZEALER"; 20 | private String ivParameter="0123456789ABCDEF"; 21 | private static CAESOperator instance=null; 22 | public CAESOperator(){ 23 | 24 | } 25 | public static CAESOperator getInstance(){ 26 | if (instance==null) 27 | instance= new CAESOperator(); 28 | return instance; 29 | } 30 | 31 | public String encrypt(String sSrc) throws Exception { 32 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 33 | byte[] raw = sKey.getBytes(); 34 | SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 35 | IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());//使用CBC模式,需要一个向量iv,可增加加密算法的强度 36 | cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); 37 | byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8")); 38 | return new String(CBase64.encode(encrypted, CBase64.DEFAULT)); 39 | } 40 | 41 | 42 | public String decrypt(String sSrc) throws Exception { 43 | try { 44 | byte[] raw = sKey.getBytes("ASCII"); 45 | SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 46 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 47 | IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes()); 48 | cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); 49 | byte[] encrypted1 = CBase64.decode(sSrc, CBase64.DEFAULT);//先用base64解密 50 | byte[] original = cipher.doFinal(encrypted1); 51 | String originalString = new String(original,"utf-8"); 52 | return originalString; 53 | } catch (Exception ex) { 54 | return null; 55 | } 56 | } 57 | 58 | public static void main(String[] args) throws Exception { 59 | // 需要加密的字符串 60 | String cSrc = "4444"; 61 | System.out.println(cSrc); 62 | String enString = CAESOperator.getInstance().encrypt(cSrc); 63 | System.out.println("加密后的字符串:\n" + enString); 64 | 65 | // 需要解密的字符串 66 | enString="cygWueIdzQwEHdivRqRBKw=="; 67 | String DeString = CAESOperator.getInstance().decrypt(enString); 68 | System.out.println("解密后的字符串:\n" + DeString); 69 | 70 | while (true) { 71 | System.out.println("chose to (de)crypt or (en)crypt"); 72 | Scanner input = new Scanner(System.in); 73 | String x = input.next(); 74 | //System.out.println(x); 75 | if (x.equals("de")){ 76 | //System.out.println("decrypt"); 77 | Scanner inputaa = new Scanner(System.in); 78 | String aa = inputaa.next(); 79 | //String data = "1AB1B76D06A15BF7D83E9629944528D9B1F4F79903E833065DC5447579E2D4AAF25250B8493677DB931CEFC0DE8B09846558F821B65F590118D0F27141EC830C003BCD9039B1962644699BCBAE2E3B81A9CF0F08904A08F2518A2391596B0AF24531ED94EBA061BADBB45FAEFFB63F91B857BB098D9E954A6BCDD8D8CDF701F72550DAFD10D6FD505A6FDACFDBBBB0340238BC905E585C1303401D43625B2C2635903CF4082E5AA949E67C6B49BF95651F93FC2B0394D1F0AF204BCC8CC8E4CA31531728C197475AD843A87F64FA03CCF6E1280A93A6536F9291FAE18D7A9A9D2EF10281291230C0905641D5A35E1D02B1D0F829EABD6B47EC7D5B02186E871018FFFC7E30854CE9C630A32B4C1D0255C02E7F713CB84BBE4CABF34CBE6A984EAD39DE804CCEEB33F1A94DE609E7510CAF1AF157CD6E84E31DC6D2F5ED3C9DA8783AB388AF49E0C67576E8708BCB96A27434E3EA23218E88C01FB7CD3279CE82B2BD8BF6124B6C921486AF2D5A150068E269A6ADF3E60A73FAF87C43E407B0D74FAD96ADC84B7FB53029FDA3BBC21C1DA9E5BB50FDD1F15B184CA51D66419783FCD34502C51FE9AC9CDE158241399DF82AECF305479CAE48A343EB44B4DFC7D524B0BC5F22B27A9EF946BBEA8CD940BF4E2FAAD8938053AB1786FF034036DA72"; 80 | String data = aa; 81 | String key = "(.2=W$j#z]d3Qx^J"; 82 | System.out.println(CAESOperator.getInstance().encrypt(cSrc)); 83 | } 84 | else if (x.equals("en")) { 85 | //System.out.println("encrypt"); 86 | Scanner inputbb = new Scanner(System.in); 87 | String bb = inputbb.next(); 88 | String key = "(.2=W$j#z]d3Qx^J"; 89 | System.out.println(CAESOperator.getInstance().decrypt(enString)); 90 | } 91 | else{ 92 | System.out.println("error"); 93 | } 94 | 95 | } 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /src/custom/CAESOperator_AES_256.java: -------------------------------------------------------------------------------- 1 | package custom; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.math.BigInteger; 5 | import java.security.MessageDigest; 6 | import java.security.NoSuchAlgorithmException; 7 | import java.security.spec.AlgorithmParameterSpec; 8 | 9 | import javax.crypto.Cipher; 10 | import javax.crypto.spec.IvParameterSpec; 11 | import javax.crypto.spec.SecretKeySpec; 12 | import javax.sound.sampled.LineListener; 13 | 14 | //import org.apache.log4j.Logger; 15 | 16 | public class CAESOperator_AES_256 { 17 | // private final static Logger logger = Logger.getLogger(EncryptUtil.class); 18 | private static final String CRYPT_METHOD = "AES"; 19 | private static final byte[] IV = "0000000000000000".getBytes(); 20 | 21 | /** 22 | * AES加密后再base64 23 | * 24 | * @param content 25 | * @return 26 | */ 27 | public static String encrypt(String content) { 28 | return encrypt(content, getKey()); 29 | } 30 | 31 | private static String encrypt(String content, byte[] bKey) { 32 | try { 33 | AlgorithmParameterSpec ivSpec = new IvParameterSpec(IV); 34 | SecretKeySpec secretKey = new SecretKeySpec(bKey, CRYPT_METHOD); 35 | 36 | Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); 37 | cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec); 38 | 39 | byte[] byteContent = padString(content).getBytes("utf-8"); 40 | byte[] result = cipher.doFinal(byteContent); 41 | 42 | return new String(CBase64.encode(result, CBase64.DEFAULT)); 43 | } 44 | catch (Exception e) { 45 | // logger.info("Exception:" + e); 46 | } 47 | 48 | return null; 49 | } 50 | 51 | public static String decrypt(String content) { 52 | return decrypt(content, getKey()); 53 | } 54 | 55 | private static String decrypt(String content, byte[] bKey) { 56 | try { 57 | // base64 decode 58 | byte[] bContent = CBase64.decode(content, CBase64.DEFAULT); 59 | 60 | AlgorithmParameterSpec ivSpec = new IvParameterSpec(IV); 61 | SecretKeySpec secretKey = new SecretKeySpec(bKey, CRYPT_METHOD); 62 | Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); 63 | cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec); 64 | // cipher.init(Cipher.DECRYPT_MODE, secretKey); 65 | byte[] result = cipher.doFinal(bContent); 66 | 67 | return new String(result).trim(); 68 | } 69 | catch (Exception e) { 70 | // logger.info("Exception:" + e); 71 | } 72 | 73 | return null; 74 | } 75 | 76 | private static String padString(String source) { 77 | char paddingChar = ' '; 78 | int size = 16; 79 | int x; 80 | try { 81 | x = source.getBytes("UTF-8").length % size; 82 | } 83 | catch (UnsupportedEncodingException e) { 84 | x = source.length(); 85 | } 86 | int padLength = size - x; 87 | StringBuilder sb = new StringBuilder(source); 88 | for (int i = 0; i < padLength; i++) { 89 | sb.append(paddingChar); 90 | // source += paddingChar; 91 | } 92 | 93 | return sb.toString();// source; 94 | } 95 | 96 | /** 97 | * same as php do. 98 | * 99 | * @param input 100 | * @return 101 | */ 102 | public static String MD5(String input) { 103 | String result = input; 104 | if (input != null) { 105 | MessageDigest md = null; 106 | try { 107 | md = MessageDigest.getInstance("MD5"); 108 | md.update(input.getBytes()); 109 | BigInteger hash = new BigInteger(1, md.digest()); 110 | result = hash.toString(16); 111 | while (result.length() < 32) { 112 | result = "0" + result; 113 | } 114 | } 115 | catch (NoSuchAlgorithmException e) { 116 | // logger.info("Exception:" + e); 117 | } 118 | } 119 | return result; 120 | } 121 | 122 | /** 123 | * 124 | * @return 125 | */ 126 | public static byte[] getKey() { 127 | //byte[] a = MD5("dye5Cx:O5").getBytes(); 128 | return MD5("dye5Cx:O5").getBytes(); 129 | } 130 | 131 | public static void main(String[] args) { 132 | System.out.println(getKey()); 133 | System.out.println(decrypt("/VWplYZ7tgFzor4LJVow+VsirJfpl0xeep2DKQZFFs78D7vLX+vVOnUbL8GCP9JpJt4W7qdFkJSx9NfHZlETjXGmvqagfoGjT+0cPnZ0bg/MXfG/sqHSzRdqI1uKpZ+/rqIAiuXcLvHCAlkroI9ljb0PEoT711TcHm73TmLs64AEx4g5Zo1k4LaMJLwmMPbS")); 134 | System.out.println(encrypt("{\"data\":{\"phone\":\"906000004\",\"cpName\":\"teddy\"},\"header\":{\"p2\":\"869011020263403\",\"p3\":\"4.4.1\",\"p17\":\"1.0\"}}")); 135 | System.out.println(encrypt("{\"code\":0,\"msg\":\"\"}")); 136 | System.out.println(decrypt("jhhiI7N1yoxKGYY0uWY3mk0ycbjxo5JmOEEur3YIufXzTHc+uJO08Q9Fu7zTOHaQ")); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/custom/CBase64.java: -------------------------------------------------------------------------------- 1 | package custom; 2 | 3 | 4 | import java.io.UnsupportedEncodingException; 5 | 6 | /** 7 | * Utilities for encoding and decoding the Base64 representation of binary data. See RFCs 2045 and 3548. 9 | */ 10 | public class CBase64 { 11 | /** 12 | * Default values for encoder/decoder flags. 13 | */ 14 | public static final int DEFAULT = 0; 15 | 16 | /** 17 | * Encoder flag bit to omit the padding '=' characters at the end of the output (if any). 18 | */ 19 | public static final int NO_PADDING = 1; 20 | 21 | /** 22 | * Encoder flag bit to omit all line terminators (i.e., the output will be on one long line). 23 | */ 24 | public static final int NO_WRAP = 2; 25 | 26 | /** 27 | * Encoder flag bit to indicate lines should be terminated with a CRLF pair instead of just an 28 | * LF. Has no effect if {@code NO_WRAP} is specified as well. 29 | */ 30 | public static final int CRLF = 4; 31 | 32 | /** 33 | * Encoder/decoder flag bit to indicate using the "URL and filename safe" variant of Base64 (see 34 | * RFC 3548 section 4) where {@code -} and {@code _} are used in place of {@code +} and {@code 35 | * /}. 36 | */ 37 | public static final int URL_SAFE = 8; 38 | 39 | /** 40 | * Flag to pass to {@link Base64OutputStream} to indicate that it should not close the output 41 | * stream it is wrapping when it itself is closed. 42 | */ 43 | public static final int NO_CLOSE = 16; 44 | 45 | // -------------------------------------------------------- 46 | // shared code 47 | // -------------------------------------------------------- 48 | 49 | /* package */ static abstract class Coder { 50 | public byte[] output; 51 | public int op; 52 | 53 | /** 54 | * Encode/decode another block of input data. this.output is provided by the caller, and 55 | * must be big enough to hold all the coded data. On exit, this.opwill be set to the length 56 | * of the coded data. 57 | * 58 | * @param finish true if this is the final call to process for this object. Will finalize 59 | * the coder state and include any final bytes in the output. 60 | * @return true if the input so far is good; false if some error has been detected in the 61 | * input stream.. 62 | */ 63 | public abstract boolean process(byte[] input, int offset, int len, boolean finish); 64 | 65 | /** 66 | * @return the maximum number of bytes a call to process() could produce for the given 67 | * number of input bytes. This may be an overestimate. 68 | */ 69 | public abstract int maxOutputSize(int len); 70 | } 71 | 72 | // -------------------------------------------------------- 73 | // decoding 74 | // -------------------------------------------------------- 75 | 76 | /** 77 | * Decode the Base64-encoded data in input and return the data in a new byte array. 78 | *

 

The padding '=' characters at the end are considered optional, but if any 79 | * are present, there must be the correct number of them. 80 | * 81 | * @param str the input String to decode, which is converted to bytes using the default 82 | * charset 83 | * @param flags controls certain features of the decoded output. Pass {@code DEFAULT} to decode 84 | * standard Base64. 85 | * @return decoded bytes 86 | * @throws IllegalArgumentException if the input contains incorrect padding 87 | */ 88 | public static byte[] decode(String str, int flags) { 89 | return decode(str.getBytes(), flags); 90 | } 91 | 92 | /** 93 | * Decode the Base64-encoded data in input and return the data in a new byte array. 94 | *

 

The padding '=' characters at the end are considered optional, but if any 95 | * are present, there must be the correct number of them. 96 | * 97 | * @param input the input array to decode 98 | * @param flags controls certain features of the decoded output. Pass {@code DEFAULT} to decode 99 | * standard Base64. 100 | * @return decoded bytes 101 | * @throws IllegalArgumentException if the input contains incorrect padding 102 | */ 103 | public static byte[] decode(byte[] input, int flags) { 104 | return decode(input, 0, input.length, flags); 105 | } 106 | 107 | /** 108 | * Decode the Base64-encoded data in input and return the data in a new byte array. 109 | *

 

The padding '=' characters at the end are considered optional, but if any 110 | * are present, there must be the correct number of them. 111 | * 112 | * @param input the data to decode 113 | * @param offset the position within the input array at which to start 114 | * @param len the number of bytes of input to decode 115 | * @param flags controls certain features of the decoded output. Pass {@code DEFAULT} to decode 116 | * standard Base64. 117 | * @return decoded bytes for given offset and length 118 | * @throws IllegalArgumentException if the input contains incorrect padding 119 | */ 120 | public static byte[] decode(byte[] input, int offset, int len, int flags) { 121 | // Allocate space for the most data the input could represent. 122 | // (It could contain less if it contains whitespace, etc.) 123 | Decoder decoder = new Decoder(flags, new byte[len * 3 / 4]); 124 | 125 | if (!decoder.process(input, offset, len, true)) { 126 | throw new IllegalArgumentException("bad base-64"); 127 | } 128 | 129 | // Maybe we got lucky and allocated exactly enough output space. 130 | if (decoder.op == decoder.output.length) { 131 | return decoder.output; 132 | } 133 | 134 | // Need to shorten the array, so allocate a new one of the 135 | // right size and copy. 136 | byte[] temp = new byte[decoder.op]; 137 | System.arraycopy(decoder.output, 0, temp, 0, decoder.op); 138 | return temp; 139 | } 140 | 141 | /* package */ static class Decoder extends Coder { 142 | /** 143 | * Lookup table for turning bytes into their position in the Base64 alphabet. 144 | */ 145 | private static final int DECODE[] = { 146 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 147 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 148 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 149 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, 150 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 151 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, 152 | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 153 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, 154 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 155 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 156 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 157 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 158 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 159 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 160 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 162 | }; 163 | 164 | /** 165 | * Decode lookup table for the "web safe" variant (RFC 3548 sec. 4) where - and _ replace + 166 | * and /. 167 | */ 168 | private static final int DECODE_WEBSAFE[] = { 169 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 170 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 171 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, 172 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, 173 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 174 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, 175 | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 176 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, 177 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 178 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 179 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 180 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 181 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 182 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 183 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 184 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 185 | }; 186 | 187 | /** 188 | * Non-data values in the DECODE arrays. 189 | */ 190 | private static final int SKIP = -1; 191 | private static final int EQUALS = -2; 192 | 193 | /** 194 | * States 0-3 are reading through the next input tuple. State 4 is having read one '=' and 195 | * expecting exactly one more. State 5 is expecting no more data or padding characters in 196 | * the input. State 6 is the error state; an error has been detected in the input and no 197 | * future input can "fix" it. 198 | */ 199 | private int state; // state number (0 to 6) 200 | private int value; 201 | 202 | final private int[] alphabet; 203 | 204 | public Decoder(int flags, byte[] output) { 205 | this.output = output; 206 | 207 | alphabet = ((flags & URL_SAFE) == 0) ? DECODE : DECODE_WEBSAFE; 208 | state = 0; 209 | value = 0; 210 | } 211 | 212 | /** 213 | * @return an overestimate for the number of bytes {@code len} bytes could decode to. 214 | */ 215 | public int maxOutputSize(int len) { 216 | return len * 3 / 4 + 10; 217 | } 218 | 219 | /** 220 | * Decode another block of input data. 221 | * 222 | * @return true if the state machine is still healthy. false if bad base-64 data has been 223 | * detected in the input stream. 224 | */ 225 | public boolean process(byte[] input, int offset, int len, boolean finish) { 226 | if (this.state == 6) return false; 227 | 228 | int p = offset; 229 | len += offset; 230 | 231 | // Using local variables makes the decoder about 12% 232 | // faster than if we manipulate the member variables in 233 | // the loop. (Even alphabet makes a measurable 234 | // difference, which is somewhat surprising to me since 235 | // the member variable is final.) 236 | int state = this.state; 237 | int value = this.value; 238 | int op = 0; 239 | final byte[] output = this.output; 240 | final int[] alphabet = this.alphabet; 241 | 242 | while (p < len) { 243 | // Try the fast path: we're starting a new tuple and the 244 | // next four bytes of the input stream are all data 245 | // bytes. This corresponds to going through states 246 | // 0-1-2-3-0. We expect to use this method for most of 247 | // the data. 248 | // 249 | // If any of the next four bytes of input are non-data 250 | // (whitespace, etc.), value will end up negative. (All 251 | // the non-data values in decode are small negative 252 | // numbers, so shifting any of them up and or'ing them 253 | // together will result in a value with its top bit set.) 254 | // 255 | // You can remove this whole block and the output should 256 | // be the same, just slower. 257 | if (state == 0) { 258 | while (p + 4 <= len && 259 | (value = ((alphabet[input[p] & 0xff] << 18) | 260 | (alphabet[input[p + 1] & 0xff] << 12) | 261 | (alphabet[input[p + 2] & 0xff] << 6) | 262 | (alphabet[input[p + 3] & 0xff]))) >= 0) { 263 | output[op + 2] = (byte) value; 264 | output[op + 1] = (byte) (value >> 8); 265 | output[op] = (byte) (value >> 16); 266 | op += 3; 267 | p += 4; 268 | } 269 | if (p >= len) break; 270 | } 271 | 272 | // The fast path isn't available -- either we've read a 273 | // partial tuple, or the next four input bytes aren't all 274 | // data, or whatever. Fall back to the slower state 275 | // machine implementation. 276 | 277 | int d = alphabet[input[p++] & 0xff]; 278 | 279 | switch (state) { 280 | case 0: 281 | if (d >= 0) { 282 | value = d; 283 | ++state; 284 | } else if (d != SKIP) { 285 | this.state = 6; 286 | return false; 287 | } 288 | break; 289 | 290 | case 1: 291 | if (d >= 0) { 292 | value = (value << 6) | d; 293 | ++state; 294 | } else if (d != SKIP) { 295 | this.state = 6; 296 | return false; 297 | } 298 | break; 299 | 300 | case 2: 301 | if (d >= 0) { 302 | value = (value << 6) | d; 303 | ++state; 304 | } else if (d == EQUALS) { 305 | // Emit the last (partial) output tuple; 306 | // expect exactly one more padding character. 307 | output[op++] = (byte) (value >> 4); 308 | state = 4; 309 | } else if (d != SKIP) { 310 | this.state = 6; 311 | return false; 312 | } 313 | break; 314 | 315 | case 3: 316 | if (d >= 0) { 317 | // Emit the output triple and return to state 0. 318 | value = (value << 6) | d; 319 | output[op + 2] = (byte) value; 320 | output[op + 1] = (byte) (value >> 8); 321 | output[op] = (byte) (value >> 16); 322 | op += 3; 323 | state = 0; 324 | } else if (d == EQUALS) { 325 | // Emit the last (partial) output tuple; 326 | // expect no further data or padding characters. 327 | output[op + 1] = (byte) (value >> 2); 328 | output[op] = (byte) (value >> 10); 329 | op += 2; 330 | state = 5; 331 | } else if (d != SKIP) { 332 | this.state = 6; 333 | return false; 334 | } 335 | break; 336 | 337 | case 4: 338 | if (d == EQUALS) { 339 | ++state; 340 | } else if (d != SKIP) { 341 | this.state = 6; 342 | return false; 343 | } 344 | break; 345 | 346 | case 5: 347 | if (d != SKIP) { 348 | this.state = 6; 349 | return false; 350 | } 351 | break; 352 | } 353 | } 354 | 355 | if (!finish) { 356 | // We're out of input, but a future call could provide 357 | // more. 358 | this.state = state; 359 | this.value = value; 360 | this.op = op; 361 | return true; 362 | } 363 | 364 | // Done reading input. Now figure out where we are left in 365 | // the state machine and finish up. 366 | 367 | switch (state) { 368 | case 0: 369 | // Output length is a multiple of three. Fine. 370 | break; 371 | case 1: 372 | // Read one extra input byte, which isn't enough to 373 | // make another output byte. Illegal. 374 | this.state = 6; 375 | return false; 376 | case 2: 377 | // Read two extra input bytes, enough to emit 1 more 378 | // output byte. Fine. 379 | output[op++] = (byte) (value >> 4); 380 | break; 381 | case 3: 382 | // Read three extra input bytes, enough to emit 2 more 383 | // output bytes. Fine. 384 | output[op++] = (byte) (value >> 10); 385 | output[op++] = (byte) (value >> 2); 386 | break; 387 | case 4: 388 | // Read one padding '=' when we expected 2. Illegal. 389 | this.state = 6; 390 | return false; 391 | case 5: 392 | // Read all the padding '='s we expected and no more. 393 | // Fine. 394 | break; 395 | } 396 | 397 | this.state = state; 398 | this.op = op; 399 | return true; 400 | } 401 | } 402 | 403 | // -------------------------------------------------------- 404 | // encoding 405 | // -------------------------------------------------------- 406 | 407 | /** 408 | * Base64-encode the given data and return a newly allocated String with the result. 409 | * 410 | * @param input the data to encode 411 | * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} results 412 | * in output that adheres to RFC 2045. 413 | * @return base64 string containing encoded input 414 | */ 415 | public static String encodeToString(byte[] input, int flags) { 416 | try { 417 | return new String(encode(input, flags), "US-ASCII"); 418 | } catch (UnsupportedEncodingException e) { 419 | // US-ASCII is guaranteed to be available. 420 | throw new AssertionError(e); 421 | } 422 | } 423 | 424 | /** 425 | * Base64-encode the given data and return a newly allocated String with the result. 426 | * 427 | * @param input the data to encode 428 | * @param offset the position within the input array at which to start 429 | * @param len the number of bytes of input to encode 430 | * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} 431 | * results in output that adheres to RFC 2045. 432 | * @return base64 string containing encoded range of input 433 | */ 434 | public static String encodeToString(byte[] input, int offset, int len, int flags) { 435 | try { 436 | return new String(encode(input, offset, len, flags), "US-ASCII"); 437 | } catch (UnsupportedEncodingException e) { 438 | // US-ASCII is guaranteed to be available. 439 | throw new AssertionError(e); 440 | } 441 | } 442 | 443 | /** 444 | * Base64-encode the given data and return a newly allocated byte[] with the result. 445 | * 446 | * @param input the data to encode 447 | * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} results 448 | * in output that adheres to RFC 2045. 449 | * @return base64 encoded input as bytes 450 | */ 451 | public static byte[] encode(byte[] input, int flags) { 452 | return encode(input, 0, input.length, flags); 453 | } 454 | 455 | /** 456 | * Base64-encode the given data and return a newly allocated byte[] with the result. 457 | * 458 | * @param input the data to encode 459 | * @param offset the position within the input array at which to start 460 | * @param len the number of bytes of input to encode 461 | * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} 462 | * results in output that adheres to RFC 2045. 463 | * @return base64 encoded input as bytes 464 | */ 465 | public static byte[] encode(byte[] input, int offset, int len, int flags) { 466 | Encoder encoder = new Encoder(flags, null); 467 | 468 | // Compute the exact length of the array we will produce. 469 | int output_len = len / 3 * 4; 470 | 471 | // Account for the tail of the data and the padding bytes, if any. 472 | if (encoder.do_padding) { 473 | if (len % 3 > 0) { 474 | output_len += 4; 475 | } 476 | } else { 477 | switch (len % 3) { 478 | case 0: 479 | break; 480 | case 1: 481 | output_len += 2; 482 | break; 483 | case 2: 484 | output_len += 3; 485 | break; 486 | } 487 | } 488 | 489 | // Account for the newlines, if any. 490 | if (encoder.do_newline && len > 0) { 491 | output_len += (((len - 1) / (3 * Encoder.LINE_GROUPS)) + 1) * 492 | (encoder.do_cr ? 2 : 1); 493 | } 494 | 495 | encoder.output = new byte[output_len]; 496 | encoder.process(input, offset, len, true); 497 | 498 | if (encoder.op != output_len) { 499 | throw new AssertionError(); 500 | } 501 | 502 | return encoder.output; 503 | } 504 | 505 | /* package */ static class Encoder extends Coder { 506 | /** 507 | * Emit a new line every this many output tuples. Corresponds to a 76-character line length 508 | * (the maximum allowable according to RFC 509 | * 2045). 510 | */ 511 | public static final int LINE_GROUPS = 19; 512 | 513 | /** 514 | * Lookup table for turning Base64 alphabet positions (6 bits) into output bytes. 515 | */ 516 | private static final byte ENCODE[] = { 517 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 518 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 519 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 520 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', 521 | }; 522 | 523 | /** 524 | * Lookup table for turning Base64 alphabet positions (6 bits) into output bytes. 525 | */ 526 | private static final byte ENCODE_WEBSAFE[] = { 527 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 528 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 529 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 530 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_', 531 | }; 532 | 533 | final private byte[] tail; 534 | /* package */ int tailLen; 535 | private int count; 536 | 537 | final public boolean do_padding; 538 | final public boolean do_newline; 539 | final public boolean do_cr; 540 | final private byte[] alphabet; 541 | 542 | public Encoder(int flags, byte[] output) { 543 | this.output = output; 544 | 545 | do_padding = (flags & NO_PADDING) == 0; 546 | do_newline = (flags & NO_WRAP) == 0; 547 | do_cr = (flags & CRLF) != 0; 548 | alphabet = ((flags & URL_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE; 549 | 550 | tail = new byte[2]; 551 | tailLen = 0; 552 | 553 | count = do_newline ? LINE_GROUPS : -1; 554 | } 555 | 556 | /** 557 | * @return an overestimate for the number of bytes {@code len} bytes could encode to. 558 | */ 559 | public int maxOutputSize(int len) { 560 | return len * 8 / 5 + 10; 561 | } 562 | 563 | public boolean process(byte[] input, int offset, int len, boolean finish) { 564 | // Using local variables makes the encoder about 9% faster. 565 | final byte[] alphabet = this.alphabet; 566 | final byte[] output = this.output; 567 | int op = 0; 568 | int count = this.count; 569 | 570 | int p = offset; 571 | len += offset; 572 | int v = -1; 573 | 574 | // First we need to concatenate the tail of the previous call 575 | // with any input bytes available now and see if we can empty 576 | // the tail. 577 | 578 | switch (tailLen) { 579 | case 0: 580 | // There was no tail. 581 | break; 582 | 583 | case 1: 584 | if (p + 2 <= len) { 585 | // A 1-byte tail with at least 2 bytes of 586 | // input available now. 587 | v = ((tail[0] & 0xff) << 16) | 588 | ((input[p++] & 0xff) << 8) | 589 | (input[p++] & 0xff); 590 | tailLen = 0; 591 | } 592 | break; 593 | 594 | case 2: 595 | if (p + 1 <= len) { 596 | // A 2-byte tail with at least 1 byte of input. 597 | v = ((tail[0] & 0xff) << 16) | 598 | ((tail[1] & 0xff) << 8) | 599 | (input[p++] & 0xff); 600 | tailLen = 0; 601 | } 602 | break; 603 | } 604 | 605 | if (v != -1) { 606 | output[op++] = alphabet[(v >> 18) & 0x3f]; 607 | output[op++] = alphabet[(v >> 12) & 0x3f]; 608 | output[op++] = alphabet[(v >> 6) & 0x3f]; 609 | output[op++] = alphabet[v & 0x3f]; 610 | if (--count == 0) { 611 | if (do_cr) output[op++] = '\r'; 612 | output[op++] = '\n'; 613 | count = LINE_GROUPS; 614 | } 615 | } 616 | 617 | // At this point either there is no tail, or there are fewer 618 | // than 3 bytes of input available. 619 | 620 | // The main loop, turning 3 input bytes into 4 output bytes on 621 | // each iteration. 622 | while (p + 3 <= len) { 623 | v = ((input[p] & 0xff) << 16) | 624 | ((input[p + 1] & 0xff) << 8) | 625 | (input[p + 2] & 0xff); 626 | output[op] = alphabet[(v >> 18) & 0x3f]; 627 | output[op + 1] = alphabet[(v >> 12) & 0x3f]; 628 | output[op + 2] = alphabet[(v >> 6) & 0x3f]; 629 | output[op + 3] = alphabet[v & 0x3f]; 630 | p += 3; 631 | op += 4; 632 | if (--count == 0) { 633 | if (do_cr) output[op++] = '\r'; 634 | output[op++] = '\n'; 635 | count = LINE_GROUPS; 636 | } 637 | } 638 | 639 | if (finish) { 640 | // Finish up the tail of the input. Note that we need to 641 | // consume any bytes in tail before any bytes 642 | // remaining in input; there should be at most two bytes 643 | // total. 644 | 645 | if (p - tailLen == len - 1) { 646 | int t = 0; 647 | v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4; 648 | tailLen -= t; 649 | output[op++] = alphabet[(v >> 6) & 0x3f]; 650 | output[op++] = alphabet[v & 0x3f]; 651 | if (do_padding) { 652 | output[op++] = '='; 653 | output[op++] = '='; 654 | } 655 | if (do_newline) { 656 | if (do_cr) output[op++] = '\r'; 657 | output[op++] = '\n'; 658 | } 659 | } else if (p - tailLen == len - 2) { 660 | int t = 0; 661 | v = (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10) | 662 | (((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2); 663 | tailLen -= t; 664 | output[op++] = alphabet[(v >> 12) & 0x3f]; 665 | output[op++] = alphabet[(v >> 6) & 0x3f]; 666 | output[op++] = alphabet[v & 0x3f]; 667 | if (do_padding) { 668 | output[op++] = '='; 669 | } 670 | if (do_newline) { 671 | if (do_cr) output[op++] = '\r'; 672 | output[op++] = '\n'; 673 | } 674 | } else if (do_newline && op > 0 && count != LINE_GROUPS) { 675 | if (do_cr) output[op++] = '\r'; 676 | output[op++] = '\n'; 677 | } 678 | 679 | if ((tailLen != 0 || p != len)) { 680 | throw new AssertionError(); 681 | } 682 | } else { 683 | // Save the leftovers in tail to be consumed on the next 684 | // call to encodeInternal. 685 | 686 | if (p == len - 1) { 687 | tail[tailLen++] = input[p]; 688 | } else if (p == len - 2) { 689 | tail[tailLen++] = input[p]; 690 | tail[tailLen++] = input[p + 1]; 691 | } 692 | } 693 | 694 | this.op = op; 695 | this.count = count; 696 | 697 | return true; 698 | } 699 | } 700 | 701 | private CBase64() { 702 | } // don't instantiate 703 | } 704 | -------------------------------------------------------------------------------- /src/custom/CGUI.java: -------------------------------------------------------------------------------- 1 | package custom; 2 | 3 | import java.awt.BorderLayout; 4 | import java.awt.Color; 5 | import java.awt.Cursor; 6 | import java.awt.Desktop; 7 | import java.awt.EventQueue; 8 | import java.awt.FlowLayout; 9 | import java.awt.GridBagConstraints; 10 | import java.awt.GridBagLayout; 11 | import java.awt.GridLayout; 12 | import java.awt.Insets; 13 | import java.awt.event.ActionEvent; 14 | import java.awt.event.ActionListener; 15 | import java.awt.event.MouseAdapter; 16 | import java.awt.event.MouseEvent; 17 | import java.net.URI; 18 | import java.util.ArrayList; 19 | import java.util.Arrays; 20 | import java.util.LinkedHashMap; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import javax.swing.ButtonGroup; 25 | import javax.swing.JButton; 26 | import javax.swing.JCheckBox; 27 | import javax.swing.JFrame; 28 | import javax.swing.JLabel; 29 | import javax.swing.JPanel; 30 | import javax.swing.JScrollPane; 31 | import javax.swing.JTable; 32 | import javax.swing.JTextArea; 33 | import javax.swing.JTextField; 34 | import javax.swing.RowSorter; 35 | import javax.swing.SortOrder; 36 | import javax.swing.SwingConstants; 37 | import javax.swing.border.EmptyBorder; 38 | import javax.swing.border.EtchedBorder; 39 | import javax.swing.table.DefaultTableModel; 40 | import javax.swing.table.TableModel; 41 | import javax.swing.table.TableRowSorter; 42 | 43 | import burp.IParameter; 44 | import burp.Parameter; 45 | 46 | public class CGUI extends JFrame { 47 | public JCheckBox chckbxProxy; 48 | public JCheckBox chckbxScanner; 49 | public JCheckBox chckbxIntruder; 50 | public JCheckBox chckbxRepeater; 51 | public JTextField textFieldDomain; 52 | public JTable table; 53 | public JTextField textFieldSecretKey; 54 | public JCheckBox chckbxAppendToEnd; 55 | public JCheckBox chckbxSameAsPara; 56 | public JTextField textFieldConnector; 57 | public JTextArea textAreaFinalString; 58 | public JCheckBox chckbxMD5; 59 | public JCheckBox chckbxNewCheckBox_3; 60 | public JTextArea textAreaSign; 61 | public JLabel lblconnector; 62 | public String extenderName = "Resign v2.0 by bit4"; 63 | 64 | 65 | 66 | public String secretKey; 67 | public int sortedColumn = -1; 68 | public SortOrder sortedMethod; 69 | private final ButtonGroup buttonGroup = new ButtonGroup(); 70 | private final ButtonGroup buttonGroup1 = new ButtonGroup(); 71 | public String howDealKey = ""; //sameAsPara or appendToEnd 72 | private JTextField textFieldParaConnector; 73 | public JTextField textFieldSign; 74 | private JCheckBox chckbxOnlyUseValue; 75 | private JLabel lblOrderMethod; 76 | 77 | RowSorter sorter; 78 | private JCheckBox chckbxSHA1; 79 | 80 | /** 81 | * Launch the application. 82 | */ 83 | public static void main(String[] args) { 84 | EventQueue.invokeLater(new Runnable() { 85 | public void run() { 86 | try { 87 | CGUI frame = new CGUI(); 88 | frame.setVisible(true); 89 | } catch (Exception e) { 90 | e.printStackTrace(); 91 | } 92 | } 93 | }); 94 | } 95 | 96 | /** 97 | * Create the frame. 98 | */ 99 | public CGUI() { 100 | 101 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 102 | setBounds(100, 100, 939, 694); 103 | JPanel contentPane = new JPanel(); 104 | contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 105 | contentPane.setLayout(new BorderLayout(0, 0)); 106 | setContentPane(contentPane); 107 | 108 | JPanel enableConfigPanel = new JPanel(); 109 | enableConfigPanel.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null)); 110 | FlowLayout flowLayout = (FlowLayout) enableConfigPanel.getLayout(); 111 | flowLayout.setAlignment(FlowLayout.LEFT); 112 | contentPane.add(enableConfigPanel, BorderLayout.NORTH); 113 | 114 | 115 | JPanel panel_3 = new JPanel(); 116 | panel_3.setBorder(null); 117 | enableConfigPanel.add(panel_3); 118 | panel_3.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); 119 | 120 | JLabel enableFor = new JLabel("Enable For :"); 121 | panel_3.add(enableFor); 122 | 123 | chckbxProxy = new JCheckBox("Proxy"); 124 | panel_3.add(chckbxProxy); 125 | 126 | chckbxScanner = new JCheckBox("Scanner"); 127 | panel_3.add(chckbxScanner); 128 | 129 | chckbxIntruder = new JCheckBox("Intruder"); 130 | panel_3.add(chckbxIntruder); 131 | 132 | chckbxRepeater = new JCheckBox("Repeater"); 133 | chckbxRepeater.setSelected(true); 134 | panel_3.add(chckbxRepeater); 135 | 136 | JPanel panel_1 = new JPanel(); 137 | panel_1.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null)); 138 | contentPane.add(panel_1, BorderLayout.SOUTH); 139 | panel_1.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5)); 140 | 141 | JLabel lblNewLabel = new JLabel(extenderName+" https://github.com/bit4woo"); 142 | lblNewLabel.addMouseListener(new MouseAdapter() { 143 | @Override 144 | public void mouseClicked(MouseEvent e) { 145 | try { 146 | URI uri = new URI("https://github.com/bit4woo"); 147 | Desktop desktop = Desktop.getDesktop(); 148 | if(Desktop.isDesktopSupported()&&desktop.isSupported(Desktop.Action.BROWSE)){ 149 | desktop.browse(uri); 150 | } 151 | } catch (Exception e2) { 152 | // TODO: handle exception 153 | } 154 | 155 | } 156 | @Override 157 | public void mouseEntered(MouseEvent e) { 158 | lblNewLabel.setForeground(Color.BLUE); 159 | } 160 | @Override 161 | public void mouseExited(MouseEvent e) { 162 | lblNewLabel.setForeground(Color.BLACK); 163 | } 164 | }); 165 | lblNewLabel.setHorizontalAlignment(SwingConstants.LEFT); 166 | panel_1.add(lblNewLabel); 167 | 168 | JPanel panel = new JPanel(); 169 | panel.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null)); 170 | contentPane.add(panel, BorderLayout.CENTER); 171 | panel.setLayout(new BorderLayout(0, 0)); 172 | 173 | JPanel panel_5 = new JPanel(); 174 | panel.add(panel_5, BorderLayout.NORTH); 175 | panel_5.setLayout(new GridLayout(0, 1, 0, 0)); 176 | 177 | JLabel lblURL = new JLabel("Domain:"); 178 | panel_5.add(lblURL); 179 | 180 | textFieldDomain = new JTextField(); 181 | panel_5.add(textFieldDomain); 182 | textFieldDomain.setColumns(20); 183 | 184 | JLabel lblParas = new JLabel("[1] Parameters:(Click Table Header To Sort Or Move Up And Down To Custom)"); 185 | panel_5.add(lblParas); 186 | 187 | JScrollPane panel_6 = new JScrollPane(); 188 | panel_6.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null)); 189 | panel.add(panel_6, BorderLayout.CENTER); 190 | 191 | table = new JTable(); 192 | table.getTableHeader().addMouseListener(new MouseAdapter() { 193 | @Override 194 | public void mouseClicked(MouseEvent e) { 195 | try { 196 | sortedColumn = table.getRowSorter().getSortKeys().get(0).getColumn(); 197 | //System.out.println(sortedColumn); 198 | sortedMethod = table.getRowSorter().getSortKeys().get(0).getSortOrder(); 199 | System.out.println(sortedMethod); //ASCENDING DESCENDING 200 | } catch (Exception e1) { 201 | sortedColumn = -1; //没有点击表头进行排序。 202 | sortedMethod = null; 203 | } 204 | // System.out.println(sortedColumn); 205 | // System.out.println(sortedMethod); 206 | lblOrderMethod.setText(table.getColumnName(sortedColumn)+" "+sortedMethod); 207 | } 208 | }); 209 | table.setColumnSelectionAllowed(true); 210 | table.setCellSelectionEnabled(true); 211 | table.setSurrendersFocusOnKeystroke(true); 212 | table.setFillsViewportHeight(true); 213 | table.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); 214 | DefaultTableModel tableModel = new DefaultTableModel( 215 | new Object[][][] { 216 | //{null, null}, 217 | }, 218 | new String[] { 219 | "Key", "Value","Type" 220 | }); 221 | sorter = new TableRowSorter(tableModel); 222 | table.setRowSorter(sorter); 223 | panel_6.setViewportView(table); 224 | table.setModel(tableModel); 225 | 226 | 227 | 228 | JPanel panel_7 = new JPanel(); 229 | panel.add(panel_7, BorderLayout.EAST); 230 | GridBagLayout gbl_panel_7 = new GridBagLayout(); 231 | gbl_panel_7.columnWidths = new int[]{93, 0}; 232 | gbl_panel_7.rowHeights = new int[]{23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 233 | gbl_panel_7.columnWeights = new double[]{1.0, Double.MIN_VALUE}; 234 | gbl_panel_7.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE}; 235 | panel_7.setLayout(gbl_panel_7); 236 | 237 | JButton btnMarkAsSign = new JButton("Mark As Sign Para"); 238 | btnMarkAsSign.addActionListener(new ActionListener() { 239 | public void actionPerformed(ActionEvent e) { 240 | if (table.getSelectedRow() != -1){ 241 | String signPara = table.getValueAt(table.getSelectedRow(), 0).toString(); 242 | textFieldSign.setText(signPara); 243 | } 244 | } 245 | }); 246 | 247 | JButton btnMoveDown = new JButton("Move Down"); 248 | btnMoveDown.addActionListener(new ActionListener() { 249 | public void actionPerformed(ActionEvent e) { 250 | if (table.getSelectedRow() != -1 && table.getSelectedRow()+1 <= table.getRowCount()-1){ 251 | try{ 252 | int row = table.getSelectedRow(); 253 | String xkey = table.getValueAt(row, 0).toString(); 254 | String xvalue = table.getValueAt(row, 1).toString(); 255 | String xtype = table.getValueAt(row, 2).toString(); 256 | 257 | String tmpkey = table.getValueAt(row+1, 0).toString(); 258 | String tmpvalue = table.getValueAt(row+1, 1).toString(); 259 | String tmptype = table.getValueAt(row+1, 2).toString(); 260 | 261 | //do exchange 262 | tableModel.setValueAt(tmpkey, row, 0); 263 | tableModel.setValueAt(tmpvalue, row, 1); 264 | tableModel.setValueAt(tmptype, row, 2); 265 | 266 | tableModel.setValueAt(xkey, row+1, 0); 267 | tableModel.setValueAt(xvalue, row+1, 1); 268 | tableModel.setValueAt(xtype, row+1, 2); 269 | 270 | table.setRowSelectionInterval(row+1, row+1);//set the line selected 271 | 272 | lblOrderMethod.setText("Custom Order"); 273 | }catch(Exception e1){ 274 | 275 | } 276 | 277 | 278 | } 279 | } 280 | }); 281 | 282 | JButton btnMoveUp = new JButton("Move Up"); 283 | btnMoveUp.addActionListener(new ActionListener() { 284 | public void actionPerformed(ActionEvent e) { 285 | if (table.getSelectedRow() != -1 && table.getSelectedRow()-1 >=0){ 286 | try { 287 | int row = table.getSelectedRow(); 288 | String xkey = table.getValueAt(row, 0).toString(); 289 | String xvalue = table.getValueAt(row, 1).toString(); 290 | String xtype = table.getValueAt(row, 2).toString(); 291 | 292 | String tmpkey = table.getValueAt(row-1, 0).toString(); 293 | String tmpvalue = table.getValueAt(row-1, 1).toString(); 294 | String tmptype = table.getValueAt(row-1, 2).toString(); 295 | //do exchange 296 | tableModel.setValueAt(tmpkey, row, 0); 297 | tableModel.setValueAt(tmpvalue, row, 1); 298 | tableModel.setValueAt(tmptype, row, 2); 299 | 300 | tableModel.setValueAt(xkey, row-1, 0); 301 | tableModel.setValueAt(xvalue, row-1, 1); 302 | tableModel.setValueAt(xtype, row-1, 2); 303 | 304 | table.setRowSelectionInterval(row-1, row-1); 305 | 306 | lblOrderMethod.setText("Custom Order"); 307 | } catch (Exception e2) { 308 | // TODO: handle exception 309 | } 310 | 311 | } 312 | } 313 | }); 314 | 315 | JButton btnAdd = new JButton("Add"); 316 | btnAdd.addActionListener(new ActionListener() { 317 | public void actionPerformed(ActionEvent e) { 318 | DefaultTableModel model = (DefaultTableModel) table.getModel(); 319 | model.addRow(new Object[]{"key","value"}); 320 | lblOrderMethod.setText("Custom Order"); 321 | } 322 | }); 323 | 324 | JButton btnNewButton = new JButton("Remove"); 325 | btnNewButton.addActionListener(new ActionListener() { 326 | public void actionPerformed(ActionEvent e) { 327 | int[] rowindexs = table.getSelectedRows(); 328 | for (int i=0; i < rowindexs.length; i++){ 329 | rowindexs[i] = table.convertRowIndexToModel(rowindexs[i]);//转换为Model的索引,否则排序后索引不对应。 330 | } 331 | Arrays.sort(rowindexs); 332 | 333 | DefaultTableModel tableModel = (DefaultTableModel) table.getModel(); 334 | for(int i=rowindexs.length-1;i>=0;i--){ 335 | tableModel.removeRow(rowindexs[i]); 336 | } 337 | lblOrderMethod.setText("Custom Order"); 338 | } 339 | }); 340 | 341 | lblOrderMethod = new JLabel("Custom Order"); 342 | GridBagConstraints gbc_lblOrderMethod = new GridBagConstraints(); 343 | gbc_lblOrderMethod.insets = new Insets(0, 0, 5, 0); 344 | gbc_lblOrderMethod.gridx = 0; 345 | gbc_lblOrderMethod.gridy = 0; 346 | panel_7.add(lblOrderMethod, gbc_lblOrderMethod); 347 | GridBagConstraints gbc_btnNewButton = new GridBagConstraints(); 348 | gbc_btnNewButton.insets = new Insets(0, 0, 5, 0); 349 | gbc_btnNewButton.gridx = 0; 350 | gbc_btnNewButton.gridy = 1; 351 | panel_7.add(btnNewButton, gbc_btnNewButton); 352 | GridBagConstraints gbc_btnAdd = new GridBagConstraints(); 353 | gbc_btnAdd.insets = new Insets(0, 0, 5, 0); 354 | gbc_btnAdd.gridx = 0; 355 | gbc_btnAdd.gridy = 2; 356 | panel_7.add(btnAdd, gbc_btnAdd); 357 | GridBagConstraints gbc_btnMoveUp = new GridBagConstraints(); 358 | gbc_btnMoveUp.insets = new Insets(0, 0, 5, 0); 359 | gbc_btnMoveUp.gridx = 0; 360 | gbc_btnMoveUp.gridy = 3; 361 | panel_7.add(btnMoveUp, gbc_btnMoveUp); 362 | GridBagConstraints gbc_btnMoveDown = new GridBagConstraints(); 363 | gbc_btnMoveDown.insets = new Insets(0, 0, 5, 0); 364 | gbc_btnMoveDown.gridx = 0; 365 | gbc_btnMoveDown.gridy = 4; 366 | panel_7.add(btnMoveDown, gbc_btnMoveDown); 367 | GridBagConstraints gbc_btnMarkAsSign = new GridBagConstraints(); 368 | gbc_btnMarkAsSign.insets = new Insets(0, 0, 5, 0); 369 | gbc_btnMarkAsSign.gridx = 0; 370 | gbc_btnMarkAsSign.gridy = 6; 371 | panel_7.add(btnMarkAsSign, gbc_btnMarkAsSign); 372 | 373 | textFieldSign = new JTextField(); 374 | GridBagConstraints gbc_textFieldSign = new GridBagConstraints(); 375 | gbc_textFieldSign.insets = new Insets(0, 0, 5, 0); 376 | gbc_textFieldSign.fill = GridBagConstraints.HORIZONTAL; 377 | gbc_textFieldSign.gridx = 0; 378 | gbc_textFieldSign.gridy = 7; 379 | panel_7.add(textFieldSign, gbc_textFieldSign); 380 | textFieldSign.setColumns(10); 381 | 382 | JButton button = new JButton("Show Final String"); 383 | button.addActionListener(new ActionListener() { 384 | public void actionPerformed(ActionEvent e) { 385 | //System.out.println(getOnlyValueConfig()); 386 | //System.out.println(getSignPara()); 387 | if (textFieldSign.getText().equals("")){ 388 | textAreaFinalString.setText("error! sign parameter must be specified!"); 389 | }else{ 390 | String str = combineString(getParaMapFromTable(),getOnlyValueConfig(),getParaConnector()); 391 | if (str.contains("")){ 392 | str = str.replace("", Long.toString(System.currentTimeMillis()));//需要重新赋值,否则不会被更新 393 | } 394 | textAreaFinalString.setText(str); 395 | } 396 | } 397 | }); 398 | GridBagConstraints gbc_button = new GridBagConstraints(); 399 | gbc_button.insets = new Insets(0, 0, 5, 0); 400 | gbc_button.gridx = 0; 401 | gbc_button.gridy = 9; 402 | panel_7.add(button, gbc_button); 403 | 404 | 405 | JPanel panel_8 = new JPanel(); 406 | panel_8.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null)); 407 | panel.add(panel_8, BorderLayout.SOUTH); 408 | panel_8.setLayout(new GridLayout(0, 1, 0, 0)); 409 | 410 | JLabel lblSecretKey = new JLabel("[2] Secret Key :"); 411 | panel_8.add(lblSecretKey); 412 | 413 | textFieldSecretKey = new JTextField(); 414 | panel_8.add(textFieldSecretKey); 415 | textFieldSecretKey.setHorizontalAlignment(SwingConstants.LEFT); 416 | textFieldSecretKey.setColumns(50); 417 | 418 | 419 | chckbxSameAsPara = new JCheckBox("Add secret key as a parameter. eg. key=secretkey"); 420 | panel_8.add(chckbxSameAsPara); 421 | chckbxSameAsPara.setSelected(true); 422 | buttonGroup.add(chckbxSameAsPara); 423 | 424 | chckbxAppendToEnd = new JCheckBox("Append to the end of sorted Parameters. eg. &key=secretkey"); 425 | panel_8.add(chckbxAppendToEnd); 426 | buttonGroup.add(chckbxAppendToEnd); 427 | 428 | JLabel lblNewLabel_1 = new JLabel("[3] How To Combine\uFF1A "); 429 | panel_8.add(lblNewLabel_1); 430 | 431 | chckbxOnlyUseValue = new JCheckBox("Only Use Value"); 432 | panel_8.add(chckbxOnlyUseValue); 433 | 434 | JLabel lblConnecStringBetween = new JLabel("connection string between each parameter"); 435 | panel_8.add(lblConnecStringBetween); 436 | 437 | textFieldParaConnector = new JTextField(); 438 | textFieldParaConnector.setText("&"); 439 | panel_8.add(textFieldParaConnector); 440 | textFieldParaConnector.setColumns(50); 441 | 442 | JPanel panel_2 = new JPanel(); 443 | panel_2.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null)); 444 | contentPane.add(panel_2, BorderLayout.EAST); 445 | panel_2.setLayout(new BorderLayout(0, 0)); 446 | 447 | textAreaFinalString = new JTextArea(); 448 | textAreaFinalString.setLineWrap(true); 449 | textAreaFinalString.setColumns(20); 450 | textAreaFinalString.setRows(20); 451 | panel_2.add(textAreaFinalString, BorderLayout.WEST); 452 | 453 | textAreaSign = new JTextArea(); 454 | textAreaSign.setLineWrap(true); 455 | textAreaSign.setColumns(20); 456 | panel_2.add(textAreaSign, BorderLayout.EAST); 457 | 458 | JPanel panel_10 = new JPanel(); 459 | panel_2.add(panel_10, BorderLayout.NORTH); 460 | GridBagLayout gbl_panel_10 = new GridBagLayout(); 461 | gbl_panel_10.columnWidths = new int[]{108, 43, 109, 0}; 462 | gbl_panel_10.rowHeights = new int[]{23, 0, 0, 0, 0}; 463 | gbl_panel_10.columnWeights = new double[]{0.0, 0.0, 0.0, Double.MIN_VALUE}; 464 | gbl_panel_10.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE}; 465 | panel_10.setLayout(gbl_panel_10); 466 | 467 | JLabel lblNewLabel_2 = new JLabel("Chose Sign Method:"); 468 | GridBagConstraints gbc_lblNewLabel_2 = new GridBagConstraints(); 469 | gbc_lblNewLabel_2.anchor = GridBagConstraints.WEST; 470 | gbc_lblNewLabel_2.insets = new Insets(0, 0, 5, 5); 471 | gbc_lblNewLabel_2.gridx = 0; 472 | gbc_lblNewLabel_2.gridy = 0; 473 | panel_10.add(lblNewLabel_2, gbc_lblNewLabel_2); 474 | 475 | chckbxMD5 = new JCheckBox("MD5"); 476 | chckbxMD5.setSelected(true); 477 | GridBagConstraints gbc_chckbxMD5 = new GridBagConstraints(); 478 | gbc_chckbxMD5.anchor = GridBagConstraints.NORTHWEST; 479 | gbc_chckbxMD5.insets = new Insets(0, 0, 5, 5); 480 | gbc_chckbxMD5.gridx = 0; 481 | gbc_chckbxMD5.gridy = 1; 482 | panel_10.add(chckbxMD5, gbc_chckbxMD5); 483 | buttonGroup1.add(chckbxMD5); 484 | 485 | chckbxSHA1 = new JCheckBox("SHA1"); 486 | chckbxSHA1.setSelected(true); 487 | GridBagConstraints gbc_chckbxSHA1 = new GridBagConstraints(); 488 | gbc_chckbxSHA1.insets = new Insets(0, 0, 5, 5); 489 | gbc_chckbxSHA1.gridx = 1; 490 | gbc_chckbxSHA1.gridy = 1; 491 | panel_10.add(chckbxSHA1, gbc_chckbxSHA1); 492 | buttonGroup1.add(chckbxSHA1); 493 | 494 | chckbxNewCheckBox_3 = new JCheckBox("To be Continue"); 495 | chckbxNewCheckBox_3.setSelected(true); 496 | chckbxNewCheckBox_3.setEnabled(false); 497 | GridBagConstraints gbc_chckbxNewCheckBox_3 = new GridBagConstraints(); 498 | gbc_chckbxNewCheckBox_3.insets = new Insets(0, 0, 5, 0); 499 | gbc_chckbxNewCheckBox_3.anchor = GridBagConstraints.NORTHWEST; 500 | gbc_chckbxNewCheckBox_3.gridx = 2; 501 | gbc_chckbxNewCheckBox_3.gridy = 1; 502 | panel_10.add(chckbxNewCheckBox_3, gbc_chckbxNewCheckBox_3); 503 | 504 | JPanel panel_11 = new JPanel(); 505 | panel_2.add(panel_11, BorderLayout.CENTER); 506 | 507 | JButton btnSign = new JButton("Sign"); 508 | btnSign.addActionListener(new ActionListener() { 509 | public void actionPerformed(ActionEvent e) { 510 | textAreaSign.setText(calcSign(textAreaFinalString.getText())); 511 | } 512 | }); 513 | panel_11.add(btnSign); 514 | } 515 | 516 | 517 | 518 | public int checkEnabledFor(){ 519 | //get values that should enable this extender for which Component. 520 | int status = 0; 521 | if (chckbxIntruder.isSelected()){ 522 | status +=32; 523 | } 524 | if(chckbxProxy.isSelected()){ 525 | status += 4; 526 | } 527 | if(chckbxRepeater.isSelected()){ 528 | status += 64; 529 | } 530 | if(chckbxScanner.isSelected()){ 531 | status += 16; 532 | } 533 | return status; 534 | } 535 | 536 | 537 | public void getSecKeyConfig() { 538 | secretKey = textFieldSecretKey.getText(); 539 | if(chckbxAppendToEnd.isSelected()){ 540 | howDealKey = "appendToEnd"; 541 | } 542 | else if (chckbxSameAsPara.isSelected()) { 543 | howDealKey = "sameAsPara"; 544 | } 545 | } 546 | 547 | public boolean getOnlyValueConfig() { 548 | if(chckbxOnlyUseValue.isSelected()){ 549 | return true; 550 | }else{ 551 | return false; 552 | } 553 | } 554 | 555 | public String getParaConnector() { 556 | return textFieldParaConnector.getText(); 557 | } 558 | 559 | 560 | 561 | 562 | public String getSignAlgorithm() { 563 | if (chckbxMD5.isSelected()){ 564 | return "MD5"; 565 | }else if (chckbxSHA1.isSelected()) { 566 | return "SHA1"; 567 | }else { 568 | return "null"; 569 | } 570 | } 571 | 572 | //两个核心方法:1是拼接字符串,2是计算出sign 573 | public String calcSign(String str){ 574 | String sign = "Sign Error"; 575 | //System.out.print(getSignAlgorithm()); 576 | if (getSignAlgorithm().equals("MD5")){ 577 | sign = CMD5.GetMD5Code(str); 578 | }else if (getSignAlgorithm().equals("SHA1")) { 579 | sign = CSHA1.SHA1(str); 580 | } 581 | return sign; 582 | } 583 | 584 | public String combineString(Map paraMap, boolean onlyValue, String paraConnector) { 585 | getSecKeyConfig(); 586 | 587 | String finalString = ""; 588 | 589 | 590 | if (howDealKey.equals("sameAsPara")){ 591 | secretKey = textFieldSecretKey.getText(); 592 | if(secretKey.contains("=") & secretKey.split("=").length==2){ 593 | paraMap.put(secretKey.split("=")[0], secretKey.split("=")[1]); 594 | } 595 | } 596 | 597 | 598 | if (sortedColumn == -1 || lblOrderMethod.equals("Custom Order")){//未进行排序。 599 | for(Map.Entrypara:paraMap.entrySet()){ 600 | if (!finalString.equals("")){ 601 | finalString += paraConnector; 602 | } 603 | if (onlyValue){ 604 | finalString += para.getValue(); 605 | }else { 606 | finalString += para; 607 | } 608 | } 609 | }else if(sortedColumn == 0) { 610 | if (sortedMethod.toString() == "ASCENDING"){ 611 | finalString = custom.CMapSort.combineMapEntry(custom.CMapSort.sortMapByKey(paraMap,"ASCENDING"), onlyValue, paraConnector); 612 | }else if (sortedMethod.toString() == "DESCENDING") { 613 | finalString = custom.CMapSort.combineMapEntry(custom.CMapSort.sortMapByKey(paraMap,"DESCENDING"), onlyValue, paraConnector); 614 | } 615 | } 616 | else if (sortedColumn == 1) { 617 | if (sortedMethod.toString() == "ASCENDING"){ 618 | finalString = custom.CMapSort.combineMapEntry(custom.CMapSort.sortMapByValue(paraMap,"ASCENDING"), onlyValue, paraConnector); 619 | }else if (sortedMethod.toString() == "DESCENDING") { 620 | finalString = custom.CMapSort.combineMapEntry(custom.CMapSort.sortMapByValue(paraMap,"DESCENDING"), onlyValue, paraConnector); 621 | } 622 | } 623 | 624 | 625 | if (howDealKey.equals("appendToEnd")){ 626 | secretKey = textFieldSecretKey.getText(); 627 | finalString += secretKey; 628 | } 629 | return finalString; 630 | } 631 | 632 | public String getHostFromUI(){ 633 | String domain = ""; 634 | domain = textFieldDomain.getText(); 635 | return domain ; 636 | } 637 | 638 | public List getParaFromTable(){ 639 | List tableParas = new ArrayList(); 640 | for (int i=0; i")) { 661 | return new Parameter(key, value,type); 662 | } 663 | } 664 | return null; 665 | } 666 | 667 | public LinkedHashMap getParaMapFromTable(){ 668 | LinkedHashMap tableParas = new LinkedHashMap(); 669 | for (int i=0; i sortMapByKey(Map map, String sortMethod) { 12 | if (map == null || map.isEmpty()) { 13 | return null; 14 | } 15 | if (sortMethod.equals("ASCENDING")){ 16 | Map sortMap = new TreeMap(new MapKeyComparator()); 17 | sortMap.putAll(map); 18 | return sortMap; 19 | }else if (sortMethod.equals("DESCENDING")) { 20 | Map sortMap = new TreeMap(new MapKeyComparatorDesc()); 21 | sortMap.putAll(map); 22 | return sortMap; 23 | }else { 24 | return null; 25 | } 26 | } 27 | 28 | /** 29 | * 使用 Map按value进行排序 30 | * @param map 31 | * @return 32 | */ 33 | public static Map sortMapByValue(Map map, String sortMethod) { 34 | if (map == null || map.isEmpty()) { 35 | return null; 36 | } 37 | Map sortedMap = new LinkedHashMap(); 38 | List> entryList = new ArrayList>(map.entrySet()); 39 | if (sortMethod.equals("ASCENDING")){ 40 | Collections.sort(entryList, new MapValueComparator()); 41 | }else if (sortMethod.equals("DESCENDING")) { 42 | Collections.sort(entryList, new MapValueComparatorDesc()); 43 | } 44 | Iterator> iter = entryList.iterator(); 45 | Map.Entry tmpEntry = null; 46 | while (iter.hasNext()) { 47 | tmpEntry = iter.next(); 48 | sortedMap.put(tmpEntry.getKey(), tmpEntry.getValue()); 49 | } 50 | return sortedMap; 51 | } 52 | 53 | 54 | public static String combineMapEntry(Map map, Boolean onlyValue, String connector){ 55 | String result = ""; 56 | if (onlyValue) { 57 | for (Map.Entry entry : map.entrySet()){ 58 | if (!result.equals("")){ 59 | result += connector; 60 | } 61 | result += entry.getValue(); 62 | } 63 | }else { 64 | for (Map.Entry entry : map.entrySet()){ 65 | if (!result.equals("")){ 66 | result += connector; 67 | } 68 | result += entry; 69 | } 70 | } 71 | return result; 72 | } 73 | public static void main (String[] args) { 74 | Map map = new TreeMap(); 75 | map.put("AKFC", "4kfc"); 76 | map.put("BWNBA", "3wnba"); 77 | map.put("CNBA", "2nba"); 78 | map.put("DCBA", "1cba"); 79 | Map resultMap = sortMapByKey(map,"ASCENDING"); //按Key进行升序排序 80 | System.out.println("key 升序"); 81 | for (Map.Entry entry : resultMap.entrySet()) { 82 | System.out.println(entry.getKey() + " " + entry.getValue()); 83 | } 84 | System.out.println("key 降序"); 85 | Map resultMap1 = sortMapByKey(map,"DESCENDING"); //按Key进行降序排序 86 | for (Map.Entry entry : resultMap1.entrySet()) { 87 | System.out.println(entry.getKey() + " " + entry.getValue()); 88 | } 89 | System.out.println("value 升序"); 90 | Map resultMap2 = sortMapByValue(map, "ASCENDING"); //按Value进行排序 91 | for (Map.Entry entry : resultMap2.entrySet()) { 92 | //System.out.println(entry.getKey() + " " + entry.getValue()); 93 | System.out.println(entry); 94 | } 95 | 96 | System.out.println("vale 降序"); 97 | Map resultMap3 = sortMapByValue(map, "DESCENDING"); //按Value进行排序 98 | for (Map.Entry entry : resultMap3.entrySet()) { 99 | //System.out.println(entry.getKey() + " " + entry.getValue()); 100 | System.out.println(entry); 101 | } 102 | System.out.println(combineMapEntry(resultMap1, false,"&")); 103 | } 104 | } 105 | 106 | //比较器类 107 | class MapKeyComparator implements Comparator{ 108 | public int compare(String str1, String str2) { 109 | return str1.compareTo(str2); 110 | } 111 | } 112 | 113 | 114 | class MapKeyComparatorDesc implements Comparator{ 115 | public int compare(String str1, String str2) { 116 | return -(str1.compareTo(str2)); //通过控制返回来逆序 117 | } 118 | } 119 | //比较器类 120 | class MapValueComparator implements Comparator> { 121 | public int compare(Entry me1, Entry me2) { 122 | return me1.getValue().compareTo(me2.getValue()); 123 | } 124 | } 125 | 126 | class MapValueComparatorDesc implements Comparator> { 127 | public int compare(Entry me1, Entry me2) { 128 | return -(me1.getValue().compareTo(me2.getValue())); 129 | } 130 | } -------------------------------------------------------------------------------- /src/custom/CRecalculater.java: -------------------------------------------------------------------------------- 1 | package custom; 2 | 3 | import java.util.Map; 4 | 5 | public class CRecalculater { 6 | 7 | public String sign(Map paraMap) { 8 | // TODO Auto-generated method stub 9 | return null; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/custom/CSHA1.java: -------------------------------------------------------------------------------- 1 | package custom; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.security.InvalidKeyException; 5 | import java.security.MessageDigest; 6 | import java.security.NoSuchAlgorithmException; 7 | import java.security.SecureRandom; 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 | public class CSHA1 { 18 | 19 | public static String SHA1(String decript) { 20 | try { 21 | MessageDigest digest = java.security.MessageDigest 22 | .getInstance("SHA-1"); 23 | digest.update(decript.getBytes()); 24 | byte messageDigest[] = digest.digest(); 25 | // Create Hex String 26 | StringBuffer hexString = new StringBuffer(); 27 | // 字节数组转换为 十六进制 数 28 | for (int i = 0; i < messageDigest.length; i++) { 29 | String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); 30 | if (shaHex.length() < 2) { 31 | hexString.append(0); 32 | } 33 | hexString.append(shaHex); 34 | } 35 | return hexString.toString(); 36 | 37 | } catch (NoSuchAlgorithmException e) { 38 | e.printStackTrace(); 39 | } 40 | return ""; 41 | } 42 | 43 | public static String SHA(String decript) { 44 | try { 45 | MessageDigest digest = java.security.MessageDigest 46 | .getInstance("SHA"); 47 | digest.update(decript.getBytes()); 48 | byte messageDigest[] = digest.digest(); 49 | // Create Hex String 50 | StringBuffer hexString = new StringBuffer(); 51 | // 字节数组转换为 十六进制 数 52 | for (int i = 0; i < messageDigest.length; i++) { 53 | String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); 54 | if (shaHex.length() < 2) { 55 | hexString.append(0); 56 | } 57 | hexString.append(shaHex); 58 | } 59 | return hexString.toString(); 60 | 61 | } catch (NoSuchAlgorithmException e) { 62 | e.printStackTrace(); 63 | } 64 | return ""; 65 | } 66 | 67 | public static void main(String[] args) { 68 | System.out.println(SHA1("6.1.7482c91a92b3f5f6ba09bdb3e31153d1d")); 69 | } 70 | } -------------------------------------------------------------------------------- /src/custom/CString2Other.java: -------------------------------------------------------------------------------- 1 | package custom; 2 | 3 | 4 | import java.util.HashMap; 5 | import java.util.Map; //util包含了很多java中常用的数据类型。 6 | import com.alibaba.fastjson.JSONObject; 7 | 8 | 9 | public class CString2Other { 10 | 11 | public static Map MapString2Map(String str) { 12 | Map map = new HashMap(); 13 | //String str = "{20130916110808=的非官方大哥,20140306110813=的广告费,20140305165435=二恶太}"; 14 | str = str.substring(1, str.length()-1);//去掉前后括号 15 | String[] arraydata = str.split(",");//按“,”将其分为字符数组 16 | for (int i = 0; i < arraydata.length; i++) { 17 | int j = arraydata[i].indexOf("="); 18 | map.put(arraydata[i].substring(0, j-1), arraydata[i].substring(j+1, arraydata[i].length())); 19 | } 20 | return map; 21 | } 22 | 23 | 24 | public static JSONObject JSONString2JSONObj(String str){ 25 | JSONObject jsonObject = JSONObject.parseObject(str); 26 | return jsonObject; 27 | } 28 | 29 | /** 30 | * json string to map,包含嵌套迭代处理。 31 | */ 32 | public static Map JSONOString2Map(String jsonStr){ 33 | Map map = new HashMap(); 34 | //最外层解析 35 | JSONObject json = JSONObject.parseObject(jsonStr); 36 | for(Object k : json.keySet()){ 37 | Object v = json.get(k); 38 | //如果内层还是数组的话,继续解析 39 | if(v instanceof JSONObject){//JSONArray和JSONObject的区别 40 | map.putAll(JSONOString2Map(v.toString())); 41 | } else { 42 | map.put(k.toString(), v); 43 | } 44 | } 45 | return map; 46 | } 47 | 48 | 49 | public static void main(String args[]) throws Exception { 50 | String test = "{\"order_id\":\"2011608112040003175\",\"pay_info\":{\"method\":\"GET\",\"params\":{\"amt\":\"1.00\",\"body\":\"综合意外险\",\"expiry_time\":\"1440\",\"merchant_code\":\"1512000401\",\"notify_info\":\"{}\",\"notify_url\":\"http://14.29.68.179:8092/receive/order/state/zhongan_pay\",\"order_info\":\"xx\",\"order_type\":\"insurance\",\"out_trade_no\":\"2011608112040003175\",\"pay_channel\":\"alipay^wxpay\",\"request_charset\":\"UTF-8\",\"return_url\":\"https://jr.meizu.com/h5/html/insurance/success.html\",\"sign\":\"7f44a0d33abb99309ffd73ea21bba840\",\"sign_type\":\"MD5\",\"src_type\":\"mobile\",\"subject\":\"综合意外险\"},\"uri\":\"http://cashier.itest.zhongan.com/za-cashier-web/gateway.do\"}}"; 51 | JSONObject jO = JSONString2JSONObj(test); 52 | //System.out.println(jO); 53 | Map map = JSONOString2Map(test); 54 | System.out.println(map); 55 | } 56 | } -------------------------------------------------------------------------------- /src/custom/CUnicodeDecoder.java: -------------------------------------------------------------------------------- 1 | package custom; 2 | 3 | /** 4 | * 工具类 5 | */ 6 | public class CUnicodeDecoder { 7 | 8 | /** 9 | * unicode解码(unicode编码转中文) 10 | * 11 | * @param theString 12 | * @return 13 | */ 14 | public static String unicodeDecode(String theString) { 15 | char aChar; 16 | int len = theString.length(); 17 | StringBuffer outBuffer = new StringBuffer(len); 18 | for (int x = 0; x < len;) { 19 | aChar = theString.charAt(x++); 20 | if (aChar == '\\') { 21 | aChar = theString.charAt(x++); 22 | 23 | if (aChar == 'u') { 24 | // Read the xxxx 25 | int value = 0; 26 | for (int i = 0; i < 4; i++) { 27 | aChar = theString.charAt(x++); 28 | switch (aChar) { 29 | case '0': 30 | case '1': 31 | case '2': 32 | case '3': 33 | case '4': 34 | case '5': 35 | case '6': 36 | case '7': 37 | case '8': 38 | case '9': 39 | value = (value << 4) + aChar - '0'; 40 | break; 41 | case 'a': 42 | case 'b': 43 | case 'c': 44 | case 'd': 45 | case 'e': 46 | case 'f': 47 | value = (value << 4) + 10 + aChar - 'a'; 48 | break; 49 | case 'A': 50 | case 'B': 51 | case 'C': 52 | case 'D': 53 | case 'E': 54 | case 'F': 55 | value = (value << 4) + 10 + aChar - 'A'; 56 | break; 57 | default: 58 | throw new IllegalArgumentException( 59 | "Malformed \\uxxxx encoding."); 60 | } 61 | } 62 | outBuffer.append((char) value); 63 | } else { 64 | if (aChar == 't') 65 | aChar = '\t'; 66 | else if (aChar == 'r') 67 | aChar = '\r'; 68 | else if (aChar == 'n') 69 | aChar = '\n'; 70 | else if (aChar == 'f') 71 | aChar = '\f'; 72 | outBuffer.append(aChar); 73 | } 74 | } else 75 | outBuffer.append(aChar); 76 | } 77 | return outBuffer.toString(); 78 | } 79 | public static void main(String[] args) throws Exception { 80 | //String unicodestring = "\u624b\u673a\u9a8c\u8bc1\u5931\u8d25\uff0c\u8bf7\u91cd\u65b0\u5c1d\u8bd5"; 81 | String unicodestring = "{\"code\":404,\"message\":\"\u624b\u673a\u9a8c\u8bc1\u5931\u8d25\uff0c\u8bf7\u91cd\u65b0\u5c1d\u8bd5\"}"; 82 | System.out.println(unicodeDecode(unicodestring)); 83 | } 84 | } --------------------------------------------------------------------------------