Cordova插件之MD5加密

自定义一个Cordova插件,用于进行MD5加密

Posted by catface on January 1, 2015

插件目录结构(参考官方提供的插件结构)

编码

plugin.xml配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
    id="deppon.md5"
    version="0.0.5">
    <name>Deppon MD5</name>
    <description>this is based on JavaAPI</description>

    <!-- js中间件的目录指定 -->
    <js-module src="www/md5.js" name="md5">
        <!-- target值为js调用的对象符号 -->
        <clobbers target="deppon"/>
    </js-module>

    <platform name="android">

        <!-- 原生代码 -->
        <source-file src="src/android/MD5Tool.java" target-dir="src/catface/plugin"/>
        <source-file src="src/android/BASE64Encoder.java" target-dir="src/catface/plugin"/>
        <source-file src="src/android/CharacterEncoder.java" target-dir="src/catface/plugin"/>

        <!-- 配置中间件及插件类 -->
        <config-file target="res/xml/config.xml" parent="/*">
            <!-- name值为中间件调用原生代码的对象符号 -->
            <feature name="MD5Tool">
                <!-- value值为插件类的包类路径 -->
                <param name="android-package" value="catface.plugin.MD5Tool"/>
            </feature>
        </config-file>

    </platform>

</plugin>

js中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var exec = require('cordova/exec');
var catfaceFunc = function(){};

// arg1:成功回调
// arg2:失败回调
// arg3:将要调用类配置的标识
// arg4:调用的原生代码中的方法名
// arg5:参数,json格式
catfaceFunc.prototype.str2MD5=function(str, success, error) {
    exec(success, error, "MD5Tool", "str2MD5", [str]);
};

var catfaceFunc = new catfaceFunc();
module.exports = catfaceFunc;

Java代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class MD5Tool extends CordovaPlugin {
    
    @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        
        if (action.equals("str2MD5")) {
            
            // 获取js传入的参数
            String str = args.getString(0);
            // 加密
            String result = str2MD5(str);
            if (!"".equals(result)) {
                callbackContext.success(result);
            } else {
                // 失败回调,结果传空字符串
                callbackContext.error("error");
            }
        }
        return true;
    }
    
    // MD5 + BASE64加密
    private static String str2MD5(String origin) {
        String resultString = new String(origin);
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
            byte[] buf = md.digest(resultString.getBytes());
            // BASE64Encoder + CharacterEncoder作为辅助类
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(buf);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }
}

加密中需要的两个类,不需手动修改,直接CV即可

  • BASE64Encoder

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    
      public class BASE64Encoder extends CharacterEncoder {
        
          private final static int NUMBER_ZERO = 0;
          private final static int NUMBER_ONE = 1;
          private final static int NUMBER_TWO = 2;
          private final static int NUMBER_THREE = 3;
          private final static int NUMBER_FOUR= 4;
          private final static int NUMBER_FIVE = 5;
          private final static int NUMBER_SIX= 6;
          private final static int NUMBER_SEVEN = 7;
        
          protected int bytesPerAtom() {
              return (NUMBER_THREE);
          }
        
          protected int bytesPerLine() {
              return 200;
          }
        
          private final static char pem_array[] = {
              //       0   1   2   3   4   5   6   7
                      'A','B','C','D','E','F','G','H', // 0
                      'I','J','K','L','M','N','O','P', // 1
                      'Q','R','S','T','U','V','W','X', // 2
                      'Y','Z','a','b','c','d','e','f', // 3
                      'g','h','i','j','k','l','m','n', // 4
                      'o','p','q','r','s','t','u','v', // 5
                      'w','x','y','z','0','1','2','3', // 6
                      '4','5','6','7','8','9','+','/'  // 7
              };
        
          protected void encodeAtom(OutputStream outStream, byte data[], int offset, int len)
              throws IOException {
              byte a, b, c;
        
              if (len == NUMBER_ONE) {
                  a = data[offset];
                  b = NUMBER_ZERO;
                  c = NUMBER_ZERO;
                  outStream.write(pem_array[(a >>> NUMBER_TWO) & 0x3F]);
                  outStream.write(pem_array[((a << NUMBER_FOUR) & 0x30) + ((b >>> NUMBER_FOUR) & 0xf)]);
                  outStream.write('=');
                  outStream.write('=');
              } else if (len == NUMBER_TWO) {
                  a = data[offset];
                  b = data[offset+1];
                  c = NUMBER_ZERO;
                  outStream.write(pem_array[(a >>> NUMBER_TWO) & 0x3F]);
                  outStream.write(pem_array[((a << NUMBER_FOUR) & 0x30) + ((b >>> NUMBER_FOUR) & 0xf)]);
                  outStream.write(pem_array[((b << NUMBER_TWO) & 0x3c) + ((c >>> NUMBER_SIX) & 0x3)]);
                  outStream.write('=');
              } else {
                  a = data[offset];
                  b = data[offset+1];
                  c = data[offset+2];
                  outStream.write(pem_array[(a >>> NUMBER_TWO) & 0x3F]);
                  outStream.write(pem_array[((a << NUMBER_FOUR) & 0x30) + ((b >>> NUMBER_FOUR) & 0xf)]);
                  outStream.write(pem_array[((b << NUMBER_TWO) & 0x3c) + ((c >>> NUMBER_SIX) & 0x3)]);
                  outStream.write(pem_array[c & 0x3F]);
              }
          }
      }
    
  • CharacterEncoder

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    
      import java.io.ByteArrayInputStream;
      import java.io.ByteArrayOutputStream;
      import java.io.IOException;
      import java.io.InputStream;
      import java.io.OutputStream;
      import java.io.PrintStream;
      import java.nio.ByteBuffer;
        
      public abstract class CharacterEncoder {
          protected PrintStream pStream;
          abstract protected int bytesPerAtom();
          abstract protected int bytesPerLine();
          protected void encodeBufferPrefix(OutputStream aStream) throws IOException {
              pStream = new PrintStream(aStream);
          }
        
          protected void encodeBufferSuffix(OutputStream aStream) throws IOException {
          }
        
          protected void encodeLinePrefix(OutputStream aStream, int aLength) throws IOException {
          }
        
          protected void encodeLineSuffix(OutputStream aStream) throws IOException {
              pStream.println();
          }
        
          abstract protected void encodeAtom(OutputStream aStream, byte someBytes[], int anOffset, int aLength)
                  throws IOException;
        
          protected int readFully(InputStream in, byte buffer[]) throws IOException {
              for (int i = 0; i < buffer.length; i++) {
                  int q = in.read();
                  if (q == -1) {
                      return i;
                  }
                  buffer[i] = (byte) q;
              }
              return buffer.length;
          }
        
          public void encode(InputStream inStream, OutputStream outStream) throws IOException {
              int j;
              int numBytes;
              byte tmpbuffer[] = new byte[bytesPerLine()];
        
              encodeBufferPrefix(outStream);
        
              while (true) {
                  numBytes = readFully(inStream, tmpbuffer);
                  if (numBytes == 0) {
                      break;
                  }
                  encodeLinePrefix(outStream, numBytes);
                  for (j = 0; j < numBytes; j += bytesPerAtom()) {
        
                      if ((j + bytesPerAtom()) <= numBytes) {
                          encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
                      } else {
                          encodeAtom(outStream, tmpbuffer, j, (numBytes) - j);
                      }
                  }
                  if (numBytes < bytesPerLine()) {
                      break;
                  } else {
                      encodeLineSuffix(outStream);
                  }
              }
              encodeBufferSuffix(outStream);
          }
        
          public void encode(byte aBuffer[], OutputStream aStream) throws IOException {
              ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
              encode(inStream, aStream);
          }
        
          public String encode(byte aBuffer[]) {
              ByteArrayOutputStream outStream = new ByteArrayOutputStream();
              ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
              String retVal = null;
              try {
                  encode(inStream, outStream);
                  retVal = outStream.toString("8859_1");
              } catch (Exception e) {
                  throw new Error("CharacterEncoder.encode internal error",e);
              }
              return (retVal);
          }
        
          private byte[] getBytes(ByteBuffer bb) {
            
              byte[] buf = null;
        
              if (bb.hasArray()) {
                  byte[] tmp = bb.array();
                  if ((tmp.length == bb.capacity()) && (tmp.length == bb.remaining())) {
                      buf = tmp;
                      bb.position(bb.limit());
                  }
              }
        
              if (buf == null) {
                    
                  buf = new byte[bb.remaining()];
        
                  bb.get(buf);
              }
        
              return buf;
          }
        
          public void encode(ByteBuffer aBuffer, OutputStream aStream) throws IOException {
              byte[] buf = getBytes(aBuffer);
              encode(buf, aStream);
          }
        
          public String encode(ByteBuffer aBuffer) {
              byte[] buf = getBytes(aBuffer);
              return encode(buf);
          }
        
          public void encodeBuffer(InputStream inStream, OutputStream outStream) throws IOException {
              int j;
              int numBytes;
              byte tmpbuffer[] = new byte[bytesPerLine()];
        
              encodeBufferPrefix(outStream);
        
              while (true) {
                  numBytes = readFully(inStream, tmpbuffer);
                  if (numBytes == 0) {
                      break;
                  }
                  encodeLinePrefix(outStream, numBytes);
                  for (j = 0; j < numBytes; j += bytesPerAtom()) {
                      if ((j + bytesPerAtom()) <= numBytes) {
                          encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
                      } else {
                          encodeAtom(outStream, tmpbuffer, j, (numBytes) - j);
                      }
                  }
                  encodeLineSuffix(outStream);
                  if (numBytes < bytesPerLine()) {
                      break;
                  }
              }
              encodeBufferSuffix(outStream);
          }
        
          public void encodeBuffer(byte aBuffer[], OutputStream aStream) throws IOException {
              ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
              encodeBuffer(inStream, aStream);
          }
        
          public String encodeBuffer(byte aBuffer[]) {
              ByteArrayOutputStream outStream = new ByteArrayOutputStream();
              ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
              try {
                  encodeBuffer(inStream, outStream);
              } catch (Exception e) {
                  throw new Error("CharacterEncoder.encodeBuffer internal error",e);
              }
              return (outStream.toString());
          }
        
          public void encodeBuffer(ByteBuffer aBuffer, OutputStream aStream) throws IOException {
              byte[] buf = getBytes(aBuffer);
              encodeBuffer(buf, aStream);
          }
        
          public String encodeBuffer(ByteBuffer aBuffer) {
              byte[] buf = getBytes(aBuffer);
              return encodeBuffer(buf);
          }
        
      }
    

使用方式

1
2
3
4
5
deppon.str2MD5(str, function(msg) {
    alert(msg); // 加密后结果
}, function(err) {
    alert(err); // 失败返回空字符串""
})