content: /*
   * Created by LuaView.
   * Copyright (c) 2017, Alibaba Group. All rights reserved.
   *
   * This source code is licensed under the MIT.
   * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
   */
  
  package com.taobao.luaview.util;
  
  import android.content.Context;
  
  import com.taobao.luaview.cache.AppCache;
  import com.taobao.luaview.global.Constants;
  
  import java.io.ByteArrayInputStream;
  import java.io.DataInputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.InputStream;
  import java.security.InvalidKeyException;
  import java.security.KeyFactory;
  import java.security.NoSuchAlgorithmException;
  import java.security.PrivateKey;
  import java.security.PublicKey;
  import java.security.Signature;
  import java.security.SignatureException;
  import java.security.cert.Certificate;
  import java.security.cert.CertificateFactory;
  import java.security.spec.PKCS8EncodedKeySpec;
  import java.security.spec.X509EncodedKeySpec;
  
  /**
   * 加解密验证
   *
   * @author song
   * @date 15/11/10
   */
  public class VerifyUtil {
      private static final String TAG = "VerifyUtil";
      private static final String CACHE_PUBLIC_KEY = AppCache.CACHE_PUBLIC_KEY;
  
      public static final String ALGORITHM_RSA = "RSA";
      public static final String SIGNATURE_ALGORITHM = "SHA1WithRSA";// "MD5withRSA";
      private static final String DER_CERT_509 = "X.509";
  
      /**
       * 验证rsa
       *
       * @param content
       * @param sign
       * @return
       */
      public static boolean rsa(Context context, byte[] content, byte[] sign) {
          try {
              byte[] publicKeyFileData = AppCache.getCache(CACHE_PUBLIC_KEY).get(Constants.PUBLIC_KEY_PATH);
              if(publicKeyFileData == null) {
                  final InputStream inputStream;inputStream = context.getAssets().open(Constants.PUBLIC_KEY_PATH);
                  publicKeyFileData = IOUtil.toBytes(inputStream);
                  AppCache.getCache(TAG).put(Constants.PUBLIC_KEY_PATH, publicKeyFileData);
              }
              return rsa(content, publicKeyFileData, sign);
          } catch (Exception e) {
              e.printStackTrace();
              return false;
          }
      }
  
      /**
       * 验证rsa
       *
       * @param content
       * @param publicKey
       * @param sign
       * @return
       */
      public static boolean rsa(byte[] content, byte[] publicKey, byte[] sign) {
          InputStream inputStream = null;
          try {
              PublicKey pk = AppCache.getCache(CACHE_PUBLIC_KEY).get(Constants.PUBLIC_KEY_PATH_PK);//get public key
              if(pk == null) {
                  inputStream = new ByteArrayInputStream(publicKey);
                  final CertificateFactory certFactory = CertificateFactory.getInstance(DER_CERT_509);
                  final Certificate cert = certFactory.generateCertificate(inputStream);
                  pk = cert.getPublicKey();
                  AppCache.getCache(CACHE_PUBLIC_KEY).put(Constants.PUBLIC_KEY_PATH_PK, pk);//cache public key
              }
              final Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
              sig.initVerify(pk);
              sig.update(content);
              if (sig.verify(sign)) {
                  return true;
              } else {
                  LogUtil.d(TAG, "Verification Error");
                  return false;
              }
          } catch (SignatureException e) {
              e.printStackTrace();
          } catch (InvalidKeyException e) {
              e.printStackTrace();
          } catch (NoSuchAlgorithmException e) {
              e.printStackTrace();
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              try {
                  if (inputStream != null) {
                      inputStream.close();
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
          return false;
      }
  
      /**
       * read private key
       *
       * @param filename
       * @return
       */
      public static PrivateKey generatePrivateKey(final String filename) {
          try {
              File f = new File(filename);
              FileInputStream fis = new FileInputStream(f);
              DataInputStream dis = new DataInputStream(fis);
              byte[] keyBytes = new byte[(int) f.length()];
              dis.readFully(keyBytes);
              dis.close();
              PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
              KeyFactory kf = KeyFactory.getInstance(ALGORITHM_RSA);
              return kf.generatePrivate(spec);
          } catch (Exception e) {
              e.printStackTrace();
              return null;
          }
      }
  
      /**
       * read public key
       *
       * @param filename
       * @return
       */
      private static PublicKey generatePublicKey(final String filename) {
          try {
              File f = new File(filename);
              FileInputStream fis = new FileInputStream(f);
              DataInputStream dis = new DataInputStream(fis);
              byte[] keyBytes = new byte[(int) f.length()];
              dis.readFully(keyBytes);
              dis.close();
  
              X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
              KeyFactory kf = KeyFactory.getInstance(ALGORITHM_RSA);
              return kf.generatePublic(spec);
          } catch (Exception e) {
              e.printStackTrace();
              return null;
          }
      }
  
      /**
       * 16 进制 to bytes
       *
       * @param s
       * @return
       */
      private static byte[] hexToBytes(String s) {
          int len = s.length();
          byte[] data = new byte[len / 2];
          for (int i = 0; i < len; i += 2) {
              data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                      + Character.digit(s.charAt(i + 1), 16));
          }
          return data;
      }
  }
  