------------------ 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证书与私钥,必须设置密码。 用这个私钥生成数字签名时,就输入密码。

2. 从私钥中提取公钥
用openssl标准命令,
opesnssl rsa -in private.pem -pubout -out public.pem
3. 生成签名文件
用openssl标准命令,
 openssl dgst -sha256 -sign private.pem -out cw.signature cw.origin

4. 公钥字串解析
用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解析。

5. 数字签名验证
用命令方式验证: 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 ];

    unsigned sign_len = sizeof( sign );

    RSA*  rsa_pri_key = RSA_generate_key( XRSA_KEY_BITS ,  , 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(  != r && sizeof( sign ) == sign_len );

    printf("%d \n", __LINE__);

     ) {
        printf(" rsa verify ok \n");
    }else{
        printf(" rsa verify faile \n");
    }

    RSA_free( rsa_pub_key );
    RSA_free( rsa_pri_key );

    ;
}

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

/*
 * Copyright (C) 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
 *
 * 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 {
    /**
     * @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;
    }

    /**
     * @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;
    }

    /**
     * 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());
        }
    }

    /**
     * @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);

        BigInteger N = key.getModulus();

        StringBuilder result = new StringBuilder();

        int nwords = N.bitLength() / 32;    // # of 32 bit integers in modulus

        if (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();
    }

    /**
     * @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);

        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<String> strarr = new ArrayList<String> ();
            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++) {
//        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);
    }
}

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 ];
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.
    ,,,,,,,,,,,,,,,,
    ,,,,,,,,,,,,,,,,
};

char *find_str(const char *path, const char *match, int seek_pos)
{
    FILE *fp = NULL;
    unsigned ;
    const char *p = NULL;
    unsigned ;
    ;
    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, , fp);
        if( buf == *p ){
            count++;
            p++;
        }else{
            count = ;
            p = match;
        }

        if( count == length ){
            break;
        }
    }

    seek_pos = (int) ftell(fp);
    count = ;
    do{
        fread(&buf, , 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 -) = '\0';

    fprintf(log_f, "%s, result=%s, count=%d \n", __func__, result, count);

    fclose(fp);
    return result;
}

unsigned long int Reflect(unsigned long int ref, char ch)
{
    unsigned ;
    int i;
    ; i<(ch+); i++)
    {
        )
            value |=  << (ch - i);
        ;
    }
    return value;
}
void creat_table(void)
{
    unsigned long i32,j32;
    unsigned long nData32;
    unsigned long nAccum32;
    ; i32<; i32++)
    {
        nData32 = (unsigned );
        nAccum32 = ;
        ; j32<; j32++)
        {
            if ((nData32 ^ nAccum32) & 0x80000000)
                nAccum32 = (nAccum32 << ) ^ cnCRC_32;
            else
                nAccum32 <<= ;
            nData32 <<= ;
        }
        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 = ;
    creat_table();
    while (size--)
    {
        chtemp = *point++;
        chtemp = (unsigned );
        CRC32_1 = ((CRC32_1 << ) | chtemp) ^Table_CRC32[(CRC32_1 >> ) & 0xFF];
        ii++;
        )
            CRC32_1 = CRC32_1 ^ 0xffffffff;

    }
    ; i<; i++)
    {
        CRC32_1 = ((CRC32_1 << )) ^ Table_CRC32[(CRC32_1 >> ) & 0xFF];
        ii++;
        )
            CRC32_1 = CRC32_1 ^ 0xffffffff;
    }
    CRC32_1 = Reflect(CRC32_1, );
    CRC32_1 = CRC32_1 ^ 0xffffffff;
    return CRC32_1;
}
int get_crc( char *path)
{
    FILE *fp;
    unsigned char *buf;
    unsigned ;
    fpos_t fpos;
    ;
    int file_size;
    int i;
    int ret;

    fp = fopen(path ,"r");

    if( fp == NULL ) {
        printf(" %s, open %s error \n" , __func__, path);
        ;
    }

    ret = fseek(fp, , SEEK_END);
    file_size = (int)ftell(fp);
    //file_size = fpos;
    buf = (unsigned char *)malloc(file_size);
    ret = fseek(fp, , SEEK_SET);
    readnum = fread(buf, , file_size, fp);
    fclose(fp);
    //for (i=0; i<file_size; i++)
    //    checksum += buf[i];
    checksum = crc32(buf, readnum);

    return checksum;
}

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

    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, , src_fp);
        fwrite(&buf, , dest_fp);
    }
    fclose(src_fp);
    fclose(dest_fp);
}

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

    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 = );
            cert->public_key = (RSAPublicKey*)malloc(sizeof(RSAPublicKey));

            char start_char;
            ) goto exit;
            if (start_char == '{') {
                // a version 1 key has no version specifier.
                cert->public_key->exponent = ;
                cert->hash_len = SHA_DIGEST_SIZE;
            } else if (start_char == 'v') {
                int version;
                ) goto exit;
                switch (version) {
                    :
                        cert->public_key->exponent = ;
                        cert->hash_len = SHA_DIGEST_SIZE;
                        break;
                    :
                        cert->public_key->exponent = ;
                        cert->hash_len = SHA256_DIGEST_SIZE;
                        break;
                    :
                        cert->public_key->exponent = ;
                        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[])) != ) {
                goto exit;
            }
            if (key->len != RSANUMWORDS) {
                printf("key length (%d) does not match expected size\n", key->len);
                goto exit;
            }
            ; i < key->len; ++i) {
                ) goto exit;
            }
            ])) != ) goto exit;
            ; i < key->len; ++i) {
                ) 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;

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

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

// return a[] >= mod
static int geM(const RSAPublicKey* key,
               const uint32_t* a) {
    int i;
    for (i = key->len; i;) {
        --i;
        ;
        ;
    }
    ;  // equal
}

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

    ; i < key->len; ++i) {
        A = (A >> ) + (uint64_t)a * b[i] + c[i];
        B = (B >> ) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
        c[i - ] = (uint32_t)B;
    }

    A = (A >> ) + (B >> );

    c[i - ] = (uint32_t)A;

    ) {
        subM(key, c);
    }
}

// montgomery c[] = a[] * b[] / R % mod
static void montMul(const RSAPublicKey* key,
                    uint32_t* c,
                    const uint32_t* a,
                    const uint32_t* b) {
    int i;
    ; i < key->len; ++i) {
        c[i] = ;
    }
    ; 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 = ;
    int i;

    // Convert from big endian byte array to little endian word array.
    ; i < key->len; ++i) {
        uint32_t tmp =
            (inout[((key->len -  - i) * ) + ] << ) |
            (inout[((key->len -  - i) * ) + ] << ) |
            (inout[((key->len -  - i) * ) + ] << ) |
            (inout[((key->len -  - i) * ) + ] << );
        a[i] = tmp;
    }

    ) {
        aaa = aaR;  // Re-use location.
        montMul(key, aR, a, key->rr);  // aR = a * RR / R mod M
        ; i < ; i += ) {
            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
    } ) {
        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 array
    ; i >= ; --i) {
        uint32_t tmp = aaa[i];
        *inout++ = tmp >> ;
        *inout++ = tmp >> ;
        *inout++ = tmp >> ;
        *inout++ = tmp >> ;
    }
}

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[]; 

    if (key->len != RSANUMWORDS) {
        ;  // Wrong key passed in.
    }

    if (len != sizeof(buf)) {
        ;  // Wrong input length.
    }

    if (hash_len != SHA_DIGEST_SIZE &&
        hash_len != SHA256_DIGEST_SIZE) {
        ;  // Unsupported hash.
    }

     && key->exponent != ) {
        fprintf(log_f, "%s, %d \n", __func__, __LINE__);
        ;  // 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");
    ; i< ; i++){
        fprintf(log_f, "%0X, ",  *p_hash);
        p_hash++;
    }

    ; i < len; ++i) {  // Copy input to local workspace.
        buf[i] = signature[i];
    }

    modpow(key, buf);  // In-place exponentiation.

    ; i < len - hash_len; ++i){
        if( buf[i] !=  sha256_padding[i] ){
            printf("padding: buf[%d]=%0X \n", i, buf[i]);
            ;
        }
    }

    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)]);
              ;
         }
    }

    ;  // All checked out OK.
}

unsigned char check_rsa_sha256(char  *file_name){
    FILE *fp = NULL;
    FILE *fp1 = NULL;
    unsigned ];
    char *origin_buf;
    unsigned char result;
    char *signature_file = "cw_signature";
    char *origin_file = "cw_origin";
    ;

    chdir("/data/media/0");
    fp = fopen(file_name, "r");
    if( fp == NULL ) {
        printf(" %s, open %s error \n" , __func__, file_name);
        ;
    }

    // read signature into file
    fp1 = fopen(signature_file, "w");
    fread(buf, , fp);
    fwrite(buf, , fp1);
    fclose(fp1);

    // read origin into file
    fp1 = fopen(origin_file, "w");
    do {
        , fp) !=  ) {
            fwrite(&c, , fp1);
            fprintf(log_f, "%c", c);
        }
    }while ( ! feof(fp) ) ;
    fclose(fp1);
    fclose(fp);

    fp1 = fopen(origin_file, "r");
    fseek(fp1, , SEEK_END);
    int  origin_size =(int)ftell(fp1);
    fseek(fp1, , SEEK_SET);
    origin_buf = (char *) malloc ( sizeof(char) * origin_size);
    fread(origin_buf, sizeof(char), origin_size, fp1);
    fclose(fp1);

    ;
    Certificate* cert = NULL;
     ){
        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");
        ;
    }

    RSAPublicKey* test_key  = cert->public_key;

/*
    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, );

    free(origin_buf);

    remove("/data/media/0/cw_origin");
    remove("/data/media/0/cw_signature");

    return result;
}

static void copy_file_to_data()
{
     ){
        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 ) ) {
         ) ==  &&
           access() ==  && access() ==  ) {
            fprintf(log_f, "<----------  cota check  --------------> \n");

            char *path= NULL;
            char *str = NULL;
            char *device = NULL;
            unsigned ;
            unsigned ;
            unsigned  ;
            ];

            // rsa-sha256
            ){
                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;
            } 

            ){
                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, );
             ){
                device = find_str();
                ){
                        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, );
             ){
                device = find_str();
                ){
                        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, );
            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, );
            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");
        }
    //}    

check_exit:
        fprintf(log_f, "verification fail.  \n");
        ;    

check_success:
        fprintf(log_f, "all verification success. \n" );
        ;
}

#endif

    switch (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");
             ) {
                copy_file_to_data();
            }
            fclose(log_f);
            ensure_path_unmounted("/data");

            return;
#endif    

RSA_SHA256数字签名的更多相关文章

  1. 2、摘要函数——MD2/MD4/MD5数字签名

    摘要是用来防止数据被私自改动的方法,其中用到的函数叫做摘要函数.这些函数的输入可以是任意大小的信息,但是输出是大小固定的摘要.摘要有个重要的特性:如果改变了输入信息的任何内容,即使改变一位,输出也将发 ...

  2. Android 数字签名

    一个ApK如果要安装到手机上,必须要一个数字签名,不过你是debug也好,release也好,这个数字签名来源一个叫做证书的东西,在我们debug的时候,开发工具已经帮我们生成了一个叫做debug.k ...

  3. [Java 安全]消息摘要与数字签名

    消息摘要 算法简述 定义 它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生.如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知 ...

  4. 介绍DSA数字签名,非对称加密的另一种实现

    接下来我们介绍DSA数字签名,非对称加密的另一种实现. DSA DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS ...

  5. Win10 驱动装不上,提示:Windows 无法验证此设备所需的驱动程序的数字签名。该值受安全引导策略保护,无法进行修改或删除。

    Windows 无法验证此设备所需的驱动程序的数字签名.某软件或硬件最近有所更改,可能安装了签名错误或损毁的文件,或者安装的文件可能是来路不明的恶意软件.(代码52) 最近换了新主板,升级了Windo ...

  6. Android数字签名

    描述你对Android数字签名的理解? 数字签名就是为程序打上一个标记来作为自己的标识,是Android系统要求的,若一个Android程序没有经过数字签名,没办法安装到系统: 签名也是对apk的一种 ...

  7. cxf+spring+数字签名开发webservice(一)

    数字证书的准备         下面做的服务端和客户端证书在例子中无法加解密,不知道什么原因,我是使用正式环境中的客户端和服务端进行开发测试的,所以需要大家自己去准备证书,或者有人知道为什么jdk生成 ...

  8. winform 程序制作自己的数字签名(续)

    在上一篇文章<winform 程序制作自己的数字签名>中我们已经可以得到我们程序定制的数字签名了,但是比较讨厌的是每次编译之后,数字签名需要重新手动添加. 我们需要的是在程序编译时自动添加 ...

  9. C#编程总结(八)数字签名

    C#编程总结(八)数字签名 在日常工作中,有很多文件需要领导审阅.签名和盖章,由于公司业务开展,跨地域.跨国业务也日益普遍,领导签名盖章变得很麻烦,开始的时候人们通过邮寄.传真等方式来解决,但是耗费时 ...

随机推荐

  1. html快速入门(基础教程+资源推荐)

    1.html究竟是什么? 从字面上理解,html是超文本标记语言hyper text mark-up language的首字母缩写,指的是一种通用web页面描述语言,是用来描述我们打开浏览器就能看到的 ...

  2. Java: RandomAccessFile

    RandeomAccessFile虽然是java.io中的成员,但该类只继承了Object类,实现了DataOut, DataIn, Closeable等接口.此类的实例支持对文件的随机访问和读取.随 ...

  3. mysql 查询当天、本周,本月,上一个月的数据

    今天 select * from 表名 where to_days(时间字段名) = to_days(now()); 昨天 近7天 DAY) <= date(时间字段名) 近30天 DAY) & ...

  4. 一个面试题的解答-----从500(Id不连续)道试题库里随机抽取20道题!

    做一个考试系统的项目,现在从试题库里面随机抽取20道题 比如我题库有500道题(ID不连续).题目出现了,如何解决呢,随机抽取! 1,我们先把500道题的id存进一个长度为500的数组. 2,实现代码 ...

  5. Can't connect to MySQL server on '127.0.0.1' (111)

    [root@localhost ~]# service mysqld statusmysqld 已停 (1)查看MySQL 服务是否已经开启: service mysqld  status (2)启动 ...

  6. 总结4点对学习Linux有帮助的建议(纯干货)

    学习需要足够的毅力和耐心 有些人把Linux运维看作一项冗长而枯燥的工作:有些人把linux运维看作一项得力的工具.如果是前者建议还是改变一下认识,不然不建议入门这行.毕竟linux运维工作是对人的毅 ...

  7. 【接口】【USB】1.学习笔记

    1.USB的优点: 可以热插拔,即插上后可以自动识别: 系统总线供电,USB共有四根线,一根电源线,一根地线,一根D+线,一根D-线,D+和D-线是差分输入线: 可以支持多种设备,且扩展容易,通过HU ...

  8. GestureDetectorl监听

    package com.example.gesturedetectorinterface; /** * write by harvic * 2014-9-25 * blog.csdn.net/harv ...

  9. PhoneGap初试!

    最近公司准备开发一个移动应用,方便起见准备开发web项目,用PhoneGap打包成iOS与Android平台的应用.对PhoneGap完全不了解,所以先装个试下.折腾了大半天,总算弄出点儿眉目,整理下 ...

  10. jdbc escape

    假如有这样1个查询请求,模糊查询标题中包含a%b_cc’d的记录,正确的sql应该是下面这样的:      select * from t_sch_work_info t where  t.title ...