RSA_SHA256数字签名

RSA_SHA256数字签名

------------------ rsa 加密与解密 -----------------------------

数论知识的实际应用: rsa加密

把问题归结为对数字的加密。 被加密的数字为明文。 RSA加密通过公钥对明文进行加密, 得到密文。 网络中传输的都是密文。接收方收到密文, 必须有私钥才能把密文解开。即RSA解密算法通过私钥对密文进行解密。

公钥都是公开的。 私钥只有指定接收方才有。

私钥是根据公钥取的一个数,要想猜出这个数的难度非常大。

看如何生成公钥:

取两个互质的大素数,分别记为p, q. 设t=(p-1)*(q-1). 取一个与t互质的一个素数记为e。

那么公钥就是(e, p*q).

现在通过公钥取一个数, 记为d,

--------------------- 用处 -------------

rsa加密有两种使用方式,

第一是对文件内容加密,这种用途需要发送方用公钥对文件加密, 接收方用私钥对文件解密。

这种方式下,文件在网络传输中都是密文, 那么在发送方要用rsa公钥加密. 接收方用私钥解密. 所以只有私钥的接收方才能解密,看到原文. 这是rsa单纯用于文件加密的用途.

第二是对文件的sha256签名进行加密, 这种方式下,发送方要用私钥对签名进行加密,接收方用公钥进行解密。

这种方式下, 原文件不加密, rsa与sha265签名算法, 生成的密文放在文件的开头。 可完成对文件的验证. 即该文件在传输过程中有没有被修改过. 如果被修改过, 即验证失败. 而crc校验, 只能验证文件的完整性. 如果被修改, 则验证不出来.

rsa还可做ssh身份验证. git仓库的验证用户的合法性 就是用rsa身份验证. id_pub是rsa加密后的.

------------------ Rsa_sha256数字签名验证 ------------------------------
利用编译时间,把要点总结一下,也梳理一下思路。

总的思路: 发送方用sha256算法对原文件生成一个签名文件,即32个字节的hash码。 然后用rsa加密算法对此算法加密。

接收方对加密的签名解密,得到一个32个字节的hash码。 对原文件进行sha256签名计算,得到32字节的hash. 将这两个hash码比较,是否相等。 若相等, 即Rsa_sha256数字签名验证通过。

原理: 不同文件生成的hash值一定不同。

  1. 生成私钥
    用openssl标准命令,
    openssl genrsa -out private.pem

另一种生成私钥的方式是用x509方式,即生成一个包含公钥和其他信息的证书, 和一个公钥。但是生成x509证书与私钥,必须设置密码。 用这个私钥生成数字签名时,就输入密码。

  1. 从私钥中提取公钥
    用openssl标准命令,
    opesnssl rsa -in private.pem -pubout -out public.pem

  2. 生成签名文件
    用openssl标准命令,
    openssl dgst -sha256 -sign private.pem -out cw.signature cw.origin

  3. 公钥字串解析
    用openssl java库写解析程序

X509EncodedKeySpec pubkeySpec = new X509EncodedKeySpec(new BASE64Decoder().decodeBuffer(keyString));
KeyFactory keyFactory = KeyFactory.getInstance(“RSA”);
PublicKey key = keyFactory.generatePublic(pubkeySpec);
  程序里的keyString字串, 来自于公钥pem文件,但要去掉文件中第一行和最后一行。
这个在网上找了好长时间。一开始的示例,没有base64decoder编码, 结果显示invalide format.

得到publickey, 即可输出到文件, 文件再由load_keys解析。

  1. 数字签名验证
    用命令方式验证: openssl dgst -sha256 -verify public.pem -signature cw.signature cw.origin

用程序方式rsa_sha256数字签名验证, 有两个可选方法:
一, 用google libmicrypt库,进行rsa_sha256数字签名验证

直接调用这个库的接口函数, 一直没过. 把这个函数从库里邻出来, 加上了log.
根据rsa解密后的签名与原文件sha256签名,两个所得到的32个字节的hash码相同,就验证通过. 改写了这个函数. 最后达到符合我们要求的函数.

从log中可以看出思路:

the hash calculated from origin file:
C3, 56, 28, 8, D4, 37, C6, B2, 77, 1A, E2, 21, D8, EA, 93, B1, 5C, E3, A6, 9C, B
B, 9A, B5, 3C, 76, 37, FD, DF, 3C, 15, A6, F,
the hash decrypted from signature:
C3, 56, 28, 8, D4, 37, C6, B2, 77, 1A, E2, 21, D8, EA, 93, B1, 5C, E3, A6, 9C, B
B, 9A, B5, 3C, 76, 37, FD, DF, 3C, 15, A6, F, cw.crc rsa_sha256 check pass.

二, 使用开源标准openssl库的做法:
加载静态库, 进程本身体积变大
安装openssl, 可以直接调用gcc a.c -lssl, 来引用静态库, 静态库会嵌入到进程中, 会使进程

变大. 动态库以单独文件的方式存在, 多个进程可以同时引用. 不增加使用进程的体积. 以下是直接由程序生成公钥和私钥, 再读取私钥做sha1数字签名验证。

复制代码
#include <stdio.h>
#include <openssl/sha.h>
#include <openssl/rsa.h>
#include <openssl/rand.h>
#include <openssl/objects.h>
#include <assert.h>

int main()
{
unsigned char hash[ SHA_DIGEST_LENGTH ];

#ifndef XINPUT_LEN
#define XINPUT_LEN (2*1024)
#endif

#ifndef XRSA_KEY_BITS
#define XRSA_KEY_BITS (1024)
#endif#define XRSA_KEY_BITS 2048
unsigned char *input = "ccccccccc " ; //[ XINPUT_LEN ];
unsigned char sign [ XRSA_KEY_BITS/8];

unsigned sign_len = sizeof( sign );RSA*  rsa_pri_key = RSA_generate_key( XRSA_KEY_BITS , 3 , NULL , NULL );RSA*  rsa_pub_key;  // = RSAPublicKey_dup( rsa_pri_key );FILE *fp = fopen("private.key", "wb");PEM_write_RSAPrivateKey(fp, rsa_pri_key, NULL, NULL,  XRSA_KEY_BITS, NULL, NULL);fclose(fp);fp =  fopen("public.key", "wb");PEM_write_RSAPublicKey(fp, rsa_pri_key);fclose(fp);fp = fopen("/home/ligang/rsa/public.key", "rb");rsa_pub_key = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL);fclose(fp);int r = RSA_sign( NID_sha256WithRSAEncryption, input , SHA_DIGEST_LENGTH , sign , &sign_len , rsa_pri_key );assert( 0 != r && sizeof( sign ) == sign_len );printf("%d \n", __LINE__);if (RSA_verify( NID_sha256WithRSAEncryption , input, SHA_DIGEST_LENGTH , sign , sign_len , rsa_pub_key ) == 1 ) {    printf(" rsa verify ok \n");}else{    printf(" rsa verify faile \n");}RSA_free( rsa_pub_key );RSA_free( rsa_pri_key );return 0;12345678910111213141516171819202122232425262728293031

}
复制代码

----------------------- java程序将public.pem解析成数组,被google的rsa_verify函数 -------------------

复制代码
/*

  • Copyright © 2008 The Android Open Source Project

  • Licensed under the Apache License, Version 2.0 (the “License”);

  • you may not use this file except in compliance with the License.

  • You may obtain a copy of the License at

  • http://www.apache.org/licenses/LICENSE-2.0
    • 1

  • Unless required by applicable law or agreed to in writing, software

  • distributed under the License is distributed on an “AS IS” BASIS,

  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  • See the License for the specific language governing permissions and

  • limitations under the License.
    */package com.android.dumpkey;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.cert.CertificateFactory;
import java.security.cert.; //X509Certificate;import java.security.cert.Certificate;
import java.security.KeyStore;
import java.security.Key;
import java.security.
; //PublicKey;import java.security.Security;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.ECPoint;
import java.io.;
import java.nio.
;
import java.security.KeyFactory;
import java.security.spec.KeySpec;
import java.security.spec.; //X509EncodedKeySpec;import sun.misc.;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

/**

  • Command line tool to extract RSA public keys from X.509 certificates

  • and output source code with data initializers for the keys.

  • @hide
    /class DumpPublicKey {
    /
    *

    /**

    /**

    /**

    BigInteger N = key.getModulus(); StringBuilder result = new StringBuilder(); int nwords = N.bitLength() / 32;    // # of 32 bit integers in modulusif (version > 1) {     result.append("v");     result.append(Integer.toString(version));     result.append(" "); } result.append("{"); result.append(nwords); BigInteger B = BigInteger.valueOf(0x100000000L);  // 2^32 BigInteger N0inv = B.subtract(N.modInverse(B));   // -1 / N[0] mod 2^32 result.append(",0x"); result.append(N0inv.toString(16)); BigInteger R = BigInteger.valueOf(2).pow(N.bitLength()); BigInteger RR = R.multiply(R).mod(N);    // 2^4096 mod N // Write out modulus as little endian array of integers. result.append(",{"); for (int i = 0; i < nwords; ++i) {     long n = N.mod(B).longValue();     result.append(n);     if (i != nwords - 1) {         result.append(",");     }     N = N.divide(B); } result.append("}"); // Write R^2 as little endian array of integers. result.append(",{"); for (int i = 0; i < nwords; ++i) {     long rr = RR.mod(B).longValue();     result.append(rr);     if (i != nwords - 1) {         result.append(",");     }     RR = RR.divide(B); } result.append("}"); result.append("}"); return result.toString();

    }

    /**

    StringBuilder result = new StringBuilder(); result.append("v"); result.append(Integer.toString(version)); result.append(" "); BigInteger X = key.getW().getAffineX(); BigInteger Y = key.getW().getAffineY(); int nbytes = key.getParams().getCurve().getField().getFieldSize() / 8;    // # of 32 bit integers in X coordinate result.append("{"); result.append(nbytes); BigInteger B = BigInteger.valueOf(0x100L);  // 2^8 // Write out Y coordinate as array of characters. result.append(",{"); for (int i = 0; i < nbytes; ++i) {     long n = X.mod(B).longValue();     result.append(n);     if (i != nbytes - 1) {         result.append(",");     }     X = X.divide(B); } result.append("}"); // Write out Y coordinate as array of characters. result.append(",{"); for (int i = 0; i < nbytes; ++i) {     long n = Y.mod(B).longValue();     result.append(n);     if (i != nbytes - 1) {         result.append(",");     }     Y = Y.divide(B); } result.append("}"); result.append("}"); return result.toString();

    }

    static String print(PublicKey key, boolean useSHA256) throws Exception {
    if (key instanceof RSAPublicKey) {
    return printRSA((RSAPublicKey) key, useSHA256);
    } else if (key instanceof ECPublicKey) {
    return printEC((ECPublicKey) key);
    } else {
    throw new Exception("Unsupported key class: " + key.getClass().getName());
    }
    }

    private static byte[] toBytes(String str) {
    if(str == null) {
    throw new IllegalArgumentException(“binary string is null”);
    }
    char[] chs = str.toCharArray();
    byte[] bys = new byte[chs.length / 2];
    int offset = 0;
    int k = 0;
    while(k < chs.length) {
    bys[offset++] = (byte)((toInt(chs[k++]) << 4) | toInt(chs[k++]));
    }
    return bys;
    }

    private static int toInt(char a) {
    if(a >= ‘0’ && a <= ‘9’) {
    return a - ‘0’;
    }
    if(a >= ‘a’ && a <= ‘f’) {
    return a - ‘a’ + 10;
    }
    if(a >= ‘A’ && a <= ‘F’) {
    return a - ‘A’ + 10;
    }
    throw new IllegalArgumentException("parameter “” + a + "“is not hex number!”);
    }

    private static byte[] getData(String fileName) {
    File f = new File(fileName);
    InputStreamReader isr;
    ArrayList strarr = new ArrayList ();
    try {
    isr = new InputStreamReader(new FileInputStream(f));
    BufferedReader br = new BufferedReader(isr);
    String line;
    try {
    while((line = br.readLine()) != null) {
    strarr.add(line);
    }
    } catch (IOException e) {
    // TODO Auto-generated catch block e.printStackTrace();
    }
    } catch (FileNotFoundException e) {
    // TODO Auto-generated catch block e.printStackTrace();
    }

    StringBuilder sb = new StringBuilder(); for (int i = 1; i < strarr.size() - 1; i++) {
    • 1

    • 2

    • 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

    • @param key to output

    • @return a String representing this public key. If the key is a

    • version 1 key, the string will be a C initializer; this is

    • not true for newer key versions.
      */static String printEC(ECPublicKey key) throws Exception {
      int version = checkEC(key);

    • 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

    • @param key to output

    • @return a String representing this public key. If the key is a

    • version 1 key, the string will be a C initializer; this is

    • not true for newer key versions.
      */static String printRSA(RSAPublicKey key, boolean useSHA256) throws Exception {
      int version = check(key, useSHA256);

    • Perform sanity check on public key.
      */static int check(PublicKey key, boolean useSHA256) throws Exception {
      if (key instanceof RSAPublicKey) {
      return checkRSA((RSAPublicKey) key, useSHA256);
      } else if (key instanceof ECPublicKey) {
      if (!useSHA256) {
      throw new Exception(“Must use SHA-256 with EC keys!”);
      }
      return checkEC((ECPublicKey) key);
      } else {
      throw new Exception("Unsupported key class: " + key.getClass().getName());
      }
      }

    • 1

    • @param key to perform sanity checks on

    • @return version number of key. Supported versions are:

    • 5: 256-bit EC key with curve NIST P-256
    • @throws Exception if the key has the wrong size or public exponent
      */static int checkEC(ECPublicKey key) throws Exception {
      if (key.getParams().getCurve().getField().getFieldSize() != 256) {
      throw new Exception(“Curve must be NIST P-256”);
      }

      return 5;
      }

    • 1

    • 1

    • 1

    • 1

    • @param key to perform sanity checks on

    • @return version number of key. Supported versions are:

    • 1: 2048-bit RSA key with e=3 and SHA-1 hash
    • 2: 2048-bit RSA key with e=65537 and SHA-1 hash
    • 3: 2048-bit RSA key with e=3 and SHA-256 hash
    • 4: 2048-bit RSA key with e=65537 and SHA-256 hash
    • @throws Exception if the key has the wrong size or public exponent
      */static int checkRSA(RSAPublicKey key, boolean useSHA256) throws Exception {
      BigInteger pubexp = key.getPublicExponent();
      BigInteger modulus = key.getModulus();
      int version;

      if (pubexp.equals(BigInteger.valueOf(3))) {
      version = useSHA256 ? 3 : 1;
      } else if (pubexp.equals(BigInteger.valueOf(65537))) {
      version = useSHA256 ? 4 : 2;
      } else {
      throw new Exception("Public exponent should be 3 or 65537 but is " +
      pubexp.toString(10) + “.”);
      }

      if (modulus.bitLength() != 2048) {
      throw new Exception(“Modulus should be 2048 bits long but is " +
      modulus.bitLength() + " bits.”);
      }

      return version;
      }

// Log.i(“xxx”, strarr.get(i)); sb.append(strarr.get(i));
}
return sb.toString().getBytes();
}

public static byte[] toByteArray(String filename) throws IOException{              File f = new File(filename);       if(!f.exists()){           throw new FileNotFoundException(filename);       }       ByteArrayOutputStream bos = new ByteArrayOutputStream((int)f.length());       BufferedInputStream in = null;       try{           in = new BufferedInputStream(new FileInputStream(f));           int buf_size = 1024;           byte[] buffer = new byte[buf_size];           int len = 0;           while(-1 != (len = in.read(buffer,0,buf_size))){               bos.write(buffer,0,len);           }           return bos.toByteArray();       }catch (IOException e) {           e.printStackTrace();           throw e;       }finally{           try{               in.close();           }catch (IOException e) {               e.printStackTrace();           }           bos.close();       }   }   public static void main(String[] args) {    if (args.length < 1) {        System.err.println("Usage: DumpPublicKey certfile ... > source.c");        System.exit(1);    }    try {    byte[] bytes = getData(args[0]);    String keyString = "";    for(int i= 0; i< bytes.length; i++){        keyString += (char)bytes[i];    }    X509EncodedKeySpec pubkeySpec = new X509EncodedKeySpec(new BASE64Decoder().decodeBuffer(keyString));    KeyFactory keyFactory = KeyFactory.getInstance("RSA");    PublicKey key = keyFactory.generatePublic(pubkeySpec);    check(key, true);    System.out.print(print(key, true));    } catch (Exception e) {        e.printStackTrace();        System.exit(1);    }    System.exit(0);}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455

}
复制代码

Android.mk 文件:

复制代码
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := dumpkey
LOCAL_SRC_FILES := DumpPublicKey.java
LOCAL_JAR_MANIFEST := DumpPublicKey.mf
LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-host
include $(BUILD_HOST_JAVA_LIBRARY)
复制代码

用./mk mm 编译,得到dumpkey.jar文件,chmod 777 dumpkey.jar. 然后dumpkey.jar public.pem即输出被google的rsa_verify函数使用

---------------- recovery.c 中添加rsa_sha256验证 ---------------------

复制代码
#ifdef HTC_COTA_SUPPORT
#include “mincrypt/rsa.h”
#include “mincrypt/sha.h”
#include “mincrypt/sha256.h”
typedef struct Certificate {
int hash_len; // SHA_DIGEST_SIZE (SHA-1) or SHA256_DIGEST_SIZE (SHA-256)
RSAPublicKey* public_key;
} Certificate;

#endif

#ifdef HTC_COTA_SUPPORT
FILE *log_f=NULL;
unsigned long cnCRC_32 = 0x04C11DB7;
unsigned long Table_CRC32[256];
static const uint8_t sha256_padding[RSANUMBYTES] = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20,

// 32 bytes of hash go here.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12

};

char *find_str(const char *path, const char *match, int seek_pos)
{
FILE *fp = NULL;
unsigned int length = 0;
const char *p = NULL;
unsigned int count = 0;
char buf = 1;
char *result = NULL;

fp = fopen(path, "r");if( fp == NULL ) {    fprintf(log_f, "%s, open %s error \n", __func__, path);    return NULL;}p = match;while( *p != '\0'){    length++;    p++;    }p = match;fseek(fp,  seek_pos,  SEEK_SET);while( (buf != '\0') && !feof(fp)){    fread(&buf, sizeof(char), 1, fp);    if( buf == *p ){        count++;        p++;    }else{        count = 0;        p = match;    }    if( count == length ){        break;    }}seek_pos = (int) ftell(fp);count = 0;do{    fread(&buf, sizeof(char), 1, fp);    ++count;    fprintf(log_f, "%c, %0X \n", buf, buf);}while( buf >= 0x21 && buf <= 0x7E && buf != '\0' && !feof(fp) );result = (char *) malloc( sizeof(char) * count);fseek(fp, seek_pos, SEEK_SET);fread(result, sizeof(char), count, fp);*(result + count -1) = '\0';fprintf(log_f, "%s, result=%s, count=%d \n", __func__, result, count);fclose(fp);return result;12345678910111213141516171819202122232425262728293031323334353637383940414243444546

}

unsigned long int Reflect(unsigned long int ref, char ch)
{
unsigned long int value=0;
int i;
for (i=1; i<(ch+1); i++)
{
if (ref & 1)
value |= 1 << (ch - i);
ref >>= 1;
}
return value;
}
void creat_table(void)
{
unsigned long i32,j32;
unsigned long nData32;
unsigned long nAccum32;
for (i32=0; i32<256; i32++)
{
nData32 = (unsigned long)(i32 << 24);
nAccum32 = 0;
for (j32=0; j32<8; j32++)
{
if ((nData32 ^ nAccum32) & 0x80000000)
nAccum32 = (nAccum32 << 1) ^ cnCRC_32;
else
nAccum32 <<= 1;
nData32 <<= 1;
}
Table_CRC32[i32] = nAccum32;
}
}
unsigned long crc32(unsigned char *buf, unsigned long size)
{
unsigned long i;
unsigned char *point;
unsigned char chtemp;

unsigned long ii;unsigned long CRC32_1;CRC32_1 = 0x0;point = buf;ii = 0;creat_table();while (size--){    chtemp = *point++;    chtemp = (unsigned char)Reflect(chtemp, 8);    CRC32_1 = ((CRC32_1 << 8) | chtemp) ^Table_CRC32[(CRC32_1 >> 24) & 0xFF];    ii++;    if (ii==4)        CRC32_1 = CRC32_1 ^ 0xffffffff;}for (i=0; i<4; i++){    CRC32_1 = ((CRC32_1 << 8)) ^ Table_CRC32[(CRC32_1 >> 24) & 0xFF];    ii++;    if (ii==4)        CRC32_1 = CRC32_1 ^ 0xffffffff;}CRC32_1 = Reflect(CRC32_1, 32);CRC32_1 = CRC32_1 ^ 0xffffffff;return CRC32_1;123456789101112131415161718192021222324252627

}
int get_crc( char *path)
{
FILE *fp;
unsigned char *buf;
unsigned long checksum = 0;
fpos_t fpos;
int readnum = 0;
int file_size;
int i;
int ret;

fp = fopen(path ,"r");if( fp == NULL ) {    printf(" %s, open %s error \n" , __func__, path);    return -1;}ret = fseek(fp, 0, SEEK_END);file_size = (int)ftell(fp);//file_size = fpos;buf = (unsigned char *)malloc(file_size);ret = fseek(fp, 0, SEEK_SET);readnum = fread(buf, 1, file_size, fp);fclose(fp);//for (i=0; i<file_size; i++)//    checksum += buf[i];checksum = crc32(buf, readnum);return checksum;1234567891011121314151617181920

}

void copy_file(const char *src, const char *dest)
{
FILE *src_fp;
FILE *dest_fp;
char buf = 1;

src_fp = fopen(src, "r");if( src_fp == NULL) {    printf("%s, open %s error. \n", __func__, src);    return;}dest_fp = fopen(dest, "w");if( dest_fp == NULL) {    printf("%s, open %s error. \n", __func__, dest);    return;}while (! feof(src_fp)) {    fread(&buf, sizeof(char), 1, src_fp);    fwrite(&buf, sizeof(char), 1, dest_fp);}fclose(src_fp);fclose(dest_fp);123456789101112131415161718

}

static Certificate*
load_keys(const char* filename, int* numKeys) {
Certificate* out = NULL;
*numKeys = 0;

FILE* f = fopen(filename, "r");if (f == NULL) {    LOGE("opening %s: %s\n", filename, strerror(errno));    goto exit;}{    int i;    bool done = false;    while (!done) {        ++*numKeys;        out = (Certificate*)realloc(out, *numKeys * sizeof(Certificate));        Certificate* cert = out + (*numKeys - 1);        cert->public_key = (RSAPublicKey*)malloc(sizeof(RSAPublicKey));        char start_char;        if (fscanf(f, " %c", &start_char) != 1) goto exit;        if (start_char == '{') {            // a version 1 key has no version specifier.            cert->public_key->exponent = 3;            cert->hash_len = SHA_DIGEST_SIZE;        } else if (start_char == 'v') {            int version;            if (fscanf(f, "%d {", &version) != 1) goto exit;            switch (version) {                case 2:                    cert->public_key->exponent = 65537;                    cert->hash_len = SHA_DIGEST_SIZE;                    break;                case 3:                    cert->public_key->exponent = 3;                    cert->hash_len = SHA256_DIGEST_SIZE;                    break;                case 4:                    cert->public_key->exponent = 65537;                    cert->hash_len = SHA256_DIGEST_SIZE;                    break;                default:                    goto exit;            }        }        RSAPublicKey* key = cert->public_key;        if (fscanf(f, " %i , 0x%x , { %u",                   &(key->len), &(key->n0inv), &(key->n[0])) != 3) {            goto exit;        }        if (key->len != RSANUMWORDS) {            printf("key length (%d) does not match expected size\n", key->len);            goto exit;        }        for (i = 1; i < key->len; ++i) {            if (fscanf(f, " , %u", &(key->n[i])) != 1) goto exit;        }        if (fscanf(f, " } , { %u", &(key->rr[0])) != 1) goto exit;        for (i = 1; i < key->len; ++i) {            if (fscanf(f, " , %u", &(key->rr[i])) != 1) goto exit;        }        fscanf(f, " } } ");        // if the line ends in a comma, this file has more keys.switch (fgetc(f)) {        case ',':            // more keys to come.break;        case EOF:            done = true;            break;        default:            LOGE("unexpected character between keys\n");            goto exit;        }        LOGI("read key e=%d hash=%d\n", key->exponent, cert->hash_len);    }}fclose(f);return out;12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879

exit:
if (f) fclose(f);
free(out);
*numKeys = 0;
return NULL;
}

static void subM(const RSAPublicKey* key,
uint32_t* a) {
int64_t A = 0;
int i;
for (i = 0; i < key->len; ++i) {
A += (uint64_t)a[i] - key->n[i];
a[i] = (uint32_t)A;
A >>= 32;
}
}

// return a[] >= modstatic int geM(const RSAPublicKey* key,
const uint32_t* a) {
int i;
for (i = key->len; i;) {
–i;
if (a[i] < key->n[i]) return 0;
if (a[i] > key->n[i]) return 1;
}
return 1; // equal}

// montgomery c[] += a * b[] / R % modstatic void montMulAdd(const RSAPublicKey* key,
uint32_t* c,
const uint32_t a,
const uint32_t* b) {
uint64_t A = (uint64_t)a * b[0] + c[0];
uint32_t d0 = (uint32_t)A * key->n0inv;
uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
int i;

for (i = 1; i < key->len; ++i) {    A = (A >> 32) + (uint64_t)a * b[i] + c[i];    B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;    c[i - 1] = (uint32_t)B;}A = (A >> 32) + (B >> 32);c[i - 1] = (uint32_t)A;if (A >> 32) {    subM(key, c);}12345678910111213

}

// montgomery c[] = a[] * b[] / R % modstatic void montMul(const RSAPublicKey* key,
uint32_t* c,
const uint32_t* a,
const uint32_t* b) {
int i;
for (i = 0; i < key->len; ++i) {
c[i] = 0;
}
for (i = 0; i < key->len; ++i) {
montMulAdd(key, c, a[i], b);
}
}

// In-place public exponentiation.
// Input and output big-endian byte array in inout.static void modpow(const RSAPublicKey* key,
uint8_t* inout) {
uint32_t a[RSANUMWORDS];
uint32_t aR[RSANUMWORDS];
uint32_t aaR[RSANUMWORDS];
uint32_t* aaa = 0;
int i;

// Convert from big endian byte array to little endian word array.for (i = 0; i < key->len; ++i) {    uint32_t tmp =        (inout[((key->len - 1 - i) * 4) + 0] << 24) |        (inout[((key->len - 1 - i) * 4) + 1] << 16) |        (inout[((key->len - 1 - i) * 4) + 2] << 8) |        (inout[((key->len - 1 - i) * 4) + 3] << 0);    a[i] = tmp;}if (key->exponent == 65537) {    aaa = aaR;  // Re-use location.    montMul(key, aR, a, key->rr);  // aR = a * RR / R mod Mfor (i = 0; i < 16; i += 2) {        montMul(key, aaR, aR, aR);  // aaR = aR * aR / R mod M        montMul(key, aR, aaR, aaR);  // aR = aaR * aaR / R mod M        }    montMul(key, aaa, aR, a);  // aaa = aR * a / R mod M} else if (key->exponent == 3) {    aaa = aR;  // Re-use location.    montMul(key, aR, a, key->rr);  /* aR = a * RR / R mod M   */    montMul(key, aaR, aR, aR);     /* aaR = aR * aR / R mod M */    montMul(key, aaa, aaR, a);     /* aaa = aaR * a / R mod M */}// Make sure aaa < mod; aaa is at most 1x mod too large.if (geM(key, aaa)) {    subM(key, aaa);}// Convert to bigendian byte arrayfor (i = key->len - 1; i >= 0; --i) {    uint32_t tmp = aaa[i];    *inout++ = tmp >> 24;    *inout++ = tmp >> 16;    *inout++ = tmp >> 8;    *inout++ = tmp >> 0;}123456789101112131415161718192021222324252627282930313233

}

int RSA_verify1(const RSAPublicKey *key,
const uint8_t *signature,
const int len,
const char *origin,
const int origin_length,
const int hash_len) {
uint8_t buf[RSANUMBYTES];

int i;const uint8_t* padding_hash; uint8_t  origin_hash[32]; if (key->len != RSANUMWORDS) {    return 0;  // Wrong key passed in.    }if (len != sizeof(buf)) {    return 0;  // Wrong input length.    }if (hash_len != SHA_DIGEST_SIZE &&    hash_len != SHA256_DIGEST_SIZE) {    return 0;  // Unsupported hash.    }if (key->exponent != 3 && key->exponent != 65537) {    fprintf(log_f, "%s, %d \n", __func__, __LINE__);    return 0;  // Unsupported exponent.    }SHA256_hash(origin, origin_length, origin_hash);uint8_t*  p_hash = origin_hash;fprintf(log_f,"\n the hash calculated from origin file: \n");for( i=0; i< 32; i++){    fprintf(log_f, "%0X, ",  *p_hash);    p_hash++;}for (i = 0; i < len; ++i) {  // Copy input to local workspace.    buf[i] = signature[i];}modpow(key, buf);  // In-place exponentiation.for( i=0; i < len - hash_len; ++i){    if( buf[i] !=  sha256_padding[i] ){        printf("padding: buf[%d]=%0X \n", i, buf[i]);        return 0;    }}fprintf(log_f, "\n the hash decrypted from signature: \n");for (i = len - hash_len; i < len; ++i) {   fprintf(log_f, "%0X, ", buf[i]);        if( buf[i]  != origin_hash[i -( len - hash_len)] ){         fprintf(log_f, "hash: buf[%d]=%0X,  origin_hash[%d]=%0X \n",              i, buf[i], i -( len - hash_len), origin_hash[i -( len - hash_len)]);          return 0;     }}return 1;  // All checked out OK.}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849

unsigned char check_rsa_sha256(char *file_name){
FILE *fp = NULL;
FILE *fp1 = NULL;
unsigned char buf [256];
char *origin_buf;
unsigned char result;
char *signature_file = “cw_signature”;
char *origin_file = “cw_origin”;
char c = 1;

chdir("/data/media/0");fp = fopen(file_name, "r");if( fp == NULL ) {    printf(" %s, open %s error \n" , __func__, file_name);    return -1;}// read signature into filefp1 = fopen(signature_file, "w");fread(buf, sizeof(char), 256, fp);fwrite(buf, sizeof(char), 256, fp1);fclose(fp1);// read origin into filefp1 = fopen(origin_file, "w");do {      if( fread(&c, sizeof(char), 1, fp) != 0 ) {        fwrite(&c, sizeof(char), 1, fp1);        fprintf(log_f, "%c", c);        }}while ( ! feof(fp) ) ;fclose(fp1);    fclose(fp);fp1 = fopen(origin_file, "r");fseek(fp1, 0, SEEK_END);int  origin_size =(int)ftell(fp1);fseek(fp1, 0, SEEK_SET);origin_buf = (char *) malloc ( sizeof(char) * origin_size);fread(origin_buf, sizeof(char), origin_size, fp1);fclose(fp1);int num_keys = 1;Certificate* cert = NULL;if(ensure_path_mounted("/system") == 0 ){    cert = load_keys("/system/etc/key_file", &num_keys);    fprintf(log_f, "mount system partision success, load keys finish.  \n");    ensure_path_unmounted("/system");}else{    fprintf(log_f, "mount system partision fail. \ n");    ensure_path_unmounted("/system");    return 0;}RSAPublicKey* test_key  = cert->public_key;12345678910111213141516171819202122232425262728293031323334353637383940414243444546

/*
SHA256_CTX sha256_ctx;
SHA256_init(&sha256_ctx);
SHA256_update(&sha256_ctx, origin_buf, 32);
const uint8_t* hash = SHA256_final(&sha256_ctx);
*/
fprintf(log_f, “begin rsa sha256 verification. \n”);
result = RSA_verify1(test_key, buf , RSANUMBYTES, origin_buf, origin_size, 32);

free(origin_buf);remove("/data/media/0/cw_origin");remove("/data/media/0/cw_signature");return result;123456

}

static void copy_file_to_data()
{
if(ensure_path_mounted("/data") == 0 ){
copy_file("/data/media/0/cwpkg.zip", “/data/data/cwtemp/cwpkg.zip”);
copy_file("/data/media/0/cw.prop", “/data/data/cwtemp/cw.prop”);
fprintf(log_f, “copy cwpkg.zip and cw.prop to /data/data/cwtemp/ finish. \n”);
}else{
fprintf(log_f, “mount /data failure. \n”);
}
ensure_path_unmounted("/data");
}

static int verify_file1()
{
//if ( (ensure_path_mounted("/sdcard") == 0 ) ) {if(access("/data/media/0/cw.crc", 0) == 0 &&
access("/data/media/0/cw.prop", 0) == 0 && access("/data/media/0/cwpkg.zip", 0) == 0 ) {
fprintf(log_f, “<---------- cota check --------------> \n”);

char *path= NULL;        char *str = NULL;        char *device = NULL;        unsigned long  crc_r = 0;        unsigned long  crc_c = 0;        unsigned int  check = 0 ;        char cwd[80];        // rsa-sha256if ( check_rsa_sha256("cw.crc")  == 1){            check |= 0x0001;            fprintf(log_f, "cw.crc rsa_sha256 check pass. \n");        }else{            check &= ~0x0001;            fprintf(log_f, "cw.crc rsa_sha256 check not pass. \n");            //goto check_exit;            }         if ( check_rsa_sha256("cw.prop")  == 1){            check |= 0x0010;            fprintf(log_f, "cw.prop rsa_sha256 check pass. \n");        }else{            check &= ~0x0010;            fprintf(log_f, "cw.prop rsa_sha256 check not pass. \n");            //goto check_exit;            }         // check project        path="/data/media/0/cw.crc";        str = find_str(path, "project:", 256);        if(ensure_path_mounted("/system") == 0 ){            device = find_str("/system/build.prop", "ro.product.device=", 0);            if(strcmp(str, device)==0){                    check |= 0x0002;                    fprintf(log_f, "project check pass. project:%s, ro.product.device=%s \n", str, device);            }else{                    check &= ~0x0002;                    fprintf(log_f, "project check not pass. project:%s, ro.product.device=%s \n", str, device);                    //goto check_exit;                }            free(device);        }else{            fprintf(log_f, "mount system partion fail \n");            //goto check_exit;            }        ensure_path_unmounted("/system") ;        free(str);        // check cid        path="/data/media/0/cw.crc";        str = find_str(path, "cid:", 256);        if(ensure_path_mounted("/system") == 0 ){            device = find_str("/system/build.prop", "ro.cid=", 0);            if(strcmp(str, device)==0){                    check |= 0x0020;                    fprintf(log_f, "cid check pass. cid:%s, ro.cid=%s \n", str, device);            }else{                    check &= ~0x0020;                    //check |= 0x0020;                    fprintf(log_f, "cid check not pass. cid:%s, ro.cid=%s \n", str, device);                    //goto check_exit;                }            free(device);        }else{            fprintf(log_f, "mount system partion fail \n");            //goto check_exit;            }        ensure_path_unmounted("/system") ;        free(str);            // check cwpkg.zip crc        str = find_str(path, "cwpkg.zip==0x", 256);        sscanf(str, "%0x", &crc_r);            crc_c =  get_crc("/data/media/0/cwpkg.zip");        if( crc_r == crc_c ){                check |= 0x0004;                fprintf(log_f, "cwpkg.zip check pass. crc_r=%0x, crc_c=%0x. \n ", crc_r, crc_c);        }else{                check &= ~0x0004;                fprintf(log_f, "cwpkg.zip check not pass.  crc_r=%0x, crc_c=%0x. \n ", crc_r, crc_c);                //goto check_exit;            }        free(str);        // check cw.prop crc        str = find_str(path, "cw.prop==0x", 256);        sscanf(str, "%0x", &crc_r);        crc_c =  get_crc("/data/media/0/cw.prop");           if( crc_r == crc_c ){                check |= 0x0008;                fprintf(log_f, "cw.prop check pass. crc_r=%0x, crc_c=%0x. \n ", crc_r, crc_c);        }else{                check &= ~0x0008;                fprintf(log_f, "cw.prop check not pass. crc_r=%0x, crc_c=%0x. \n ", crc_r, crc_c);                //goto check_exit;            }        free(str);        fprintf(log_f, "check=%0X \n", check);            if( check == 0x003F ) {                goto check_success;        }else{                goto check_exit;        }                }else{           fprintf(log_f, "cota file not exist.  \n");    }//}    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101

check_exit:
fprintf(log_f, “verification fail. \n”);
return 0;

check_success:
fprintf(log_f, “all verification success. \n” );
return 1;
}

#endifswitch (chosen_item) {
#ifdef HTC_COTA_SUPPORT
case Device::APPLY_COTA_UPDATE:
ensure_path_mounted("/data");
log_f = fopen("/data/data/recover_log", “w”);
fprintf(log_f, “aplly cota update. \n”);
if(verify_file1() == 1 ) {
copy_file_to_data();
}
fclose(log_f);
ensure_path_unmounted("/data");

return;
(0)

相关推荐

  • 网科上网行为管理操作文档

    山石网科上网行为管理操作文档 一:登录 上网行为管理登录地址:https://192.168.5.2/ 用户名:guest 密码:guest@123 图 1 登录页面 二:用户组织结构管理 依次选择& ...

  • 几种常用加密手段的加密与解密

    网络中传输敏感信息的时候通常会对字符串做加密解密处理 1.Base64位加密(可加密解密)     最简单的加密方式,没有密钥,这种方式只要让别人拿到你的密文,就可以直接解密,只能用来迷惑,一般情况下 ...

  • 数字签名与加密算法-上【mix指南之区块链】

    为什么要开一个区块链的系列?引用mixlab社区里的熊叔(ML94)的话: " 如果把人比作手机,价值观.态度和习惯是这个操作系统底层,领域技能更像是系统上的app.技能不会的话装一个就好, ...

  • 怎样判断驱动程序是否有通过WHQL认证获得微软数字签名

    怎样判断驱动程序是否有通过WHQL认证获得微软数字签名 我们都知道通过了Windows徽标认证(WHQL)获得微软数字签名对于驱动程序的安装和使用是一个稳定象征. 然而,是不是所有微软数字签名的驱动程 ...

  • 小技巧GET: 如何验证系统文件的数字签名

    如果你想知道系统上的文件是否被非法篡改,这里我介绍给大家一个小工具:sigverif. 具体的操作方法如下 1) 打开电脑的开始,运行窗口. 2) 输入sigverif并回车,即可. 这个小工具打开后 ...

  • 如何通过数字签名技术优化供应链流程?

    一.背景 A企业是一家供应链服务公司(以下简称"公司"),为多个国外品牌商在国内市场提供销售执行.物流执行.供应链金融等服务,供货给国外品牌商的下游经销商. 公司基于ERP系统,已 ...

  • Java 获取PDF中的数字签名信息

    一.概述及程序环境要求 本文以Java代码演示如何获取PDF文档中的数字签名信息,包括签名人.签名位置.日期.原因.联系方式.签名在文档中的坐标等等. 程序环境包括: Spire.Pdf.jar(ja ...

  • C# / VB.NET 获取PDF文档的数字签名信息

    文档中的数字签名具有不可否认性,可有效防伪防篡改.对文档中已有的数字签名信息,可通过一定方法获取,下面通过程序代码介绍如何来实现.程序中,使用了Spire.PDF.dll,版本:6.11.6,可自行在 ...

  • Excel VBA使用数字签名,让你代码开启执行无忧之路

    前言:对于初学VBA的你,或许不知道VBA其实也可以是一种宏病毒,他可以悄悄的删除你计算机内的任何文件.相对于Excel而言,假如某个文件中有VBA代码,让我们大多数最担心是的一件事情便是是否存在病毒 ...

  • Win10出现Windows已阻止安装未具有数字签名的驱动程序的解决方法

    我们在使用Win10系统的过程中,可能会遇到许多问题.近期有不少网友反馈,在Win10系统中安装某设备的驱动程序时,出现了"Windows已阻止安装未具有数字签名的驱动程序"的提示 ...

  • Windows 10 低版本驱动数字签名更新的必要性

    Windows 10 低版本驱动数字签名更新的必要性 最近我们在接到一位客户的反馈,之前做的windows 10 WHQL认证获得的驱动数字签名在新版本的Windows 10 20H2无法安装,提示是 ...

  • 如何申请邮件安全证书(S/MIME)实现邮件加密和数字签名

    邮件作为目前互联网最为开放的沟通工具,在大家的工作和生活中,使用的频率非常高.特别是商务办公领域,邮件交流会涉及到很多的商业机密以及交易流程.正因为如此,邮件也会经常受到黑客或者不法分子的攻击. 那么 ...