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证书与私钥,必须设置密码。 用这个私钥生成数字签名时,就输入密码。
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数字签名的更多相关文章
- 2、摘要函数——MD2/MD4/MD5数字签名
摘要是用来防止数据被私自改动的方法,其中用到的函数叫做摘要函数.这些函数的输入可以是任意大小的信息,但是输出是大小固定的摘要.摘要有个重要的特性:如果改变了输入信息的任何内容,即使改变一位,输出也将发 ...
- Android 数字签名
一个ApK如果要安装到手机上,必须要一个数字签名,不过你是debug也好,release也好,这个数字签名来源一个叫做证书的东西,在我们debug的时候,开发工具已经帮我们生成了一个叫做debug.k ...
- [Java 安全]消息摘要与数字签名
消息摘要 算法简述 定义 它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生.如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知 ...
- 介绍DSA数字签名,非对称加密的另一种实现
接下来我们介绍DSA数字签名,非对称加密的另一种实现. DSA DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS ...
- Win10 驱动装不上,提示:Windows 无法验证此设备所需的驱动程序的数字签名。该值受安全引导策略保护,无法进行修改或删除。
Windows 无法验证此设备所需的驱动程序的数字签名.某软件或硬件最近有所更改,可能安装了签名错误或损毁的文件,或者安装的文件可能是来路不明的恶意软件.(代码52) 最近换了新主板,升级了Windo ...
- Android数字签名
描述你对Android数字签名的理解? 数字签名就是为程序打上一个标记来作为自己的标识,是Android系统要求的,若一个Android程序没有经过数字签名,没办法安装到系统: 签名也是对apk的一种 ...
- cxf+spring+数字签名开发webservice(一)
数字证书的准备 下面做的服务端和客户端证书在例子中无法加解密,不知道什么原因,我是使用正式环境中的客户端和服务端进行开发测试的,所以需要大家自己去准备证书,或者有人知道为什么jdk生成 ...
- winform 程序制作自己的数字签名(续)
在上一篇文章<winform 程序制作自己的数字签名>中我们已经可以得到我们程序定制的数字签名了,但是比较讨厌的是每次编译之后,数字签名需要重新手动添加. 我们需要的是在程序编译时自动添加 ...
- C#编程总结(八)数字签名
C#编程总结(八)数字签名 在日常工作中,有很多文件需要领导审阅.签名和盖章,由于公司业务开展,跨地域.跨国业务也日益普遍,领导签名盖章变得很麻烦,开始的时候人们通过邮寄.传真等方式来解决,但是耗费时 ...
随机推荐
- WAP站点(IIS/Apache)的服务器设置
Server 端的设置IIS服务器:为了使IIS支持WAP(WML)页面的发布,在IIS的Web站点的属性 / HTTP信息中设置WAP的MIME属性,添加如下的MIME类型:扩展名 内容类型(MIM ...
- Sublime Text 3 使用问题答疑
命令面板/命令模式:ctrl+shift+pctrl+cctrl+v → ctrl+shift+v粘贴时会保持原格式(缩进)ctrl+sctrl+z撤销ctrl+y恢复撤销在当前行下面添加一行:ctr ...
- 限制textarea输入内容长度(多浏览器兼容、鼠标操作可控)
限制textarea的输入内容长度,当从键盘输入,内容长度达到最大值时,只有输入Backspace.Delete.左移动.右移动有效,当用鼠标粘贴内容,则只保留最大值长度的内容.从而控制textare ...
- 节约内存:Instagram的Redis实践(转)
一.问题: 数据库表数据量极大(千万条),要求让服务器更加快速地响应用户的需求. 二.解决方案: 1.通过高速服务器Cache缓存数据库数据 2.内存数据库 三.主流解Ca ...
- 在代码设置RelativeLayout的属性,比如layout_below
( (RelativeLayout.LayoutParams)holder.ivLvDivider.getLayoutParams()).addRule(RelativeLayout.BELOW, R ...
- CentOS 7 Mysql yum源
CentOS 7 安装Mysqlrpm -ivh http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpmyum install m ...
- WCF初探-25:WCF中使用XmlSerializer类
前言 在上一篇WCF序列化和反序列化中,文章介绍了WCF序列化和反序列化的机制,虽然WCF针对序列化提供了默认的DataContractSerializer序列化引擎,但是WCF还支持其他的序列化引擎 ...
- js判断qq浏览器
if(navigator.userAgent.toLowerCase().toString().indexOf('qqbrowser') > -1){ console.log('qq');}el ...
- 2015年最好的PHP框架调查统计
2015年最流行的框架,Laravel框架获得赢家! 正如预期的那样,Laravel这次又一次高出了一大截. 有一些人可能会担心,部分框架分裂版本可能影响Laravel的调查结果,并给它一个不公平的优 ...
- 山锅(samgor)的博客 2014
搞移动端的前端开发已经3年,悄悄地从一个前端小白变成老油条. 项目已经做了好几个,最近发现技术的提升貌似停滞不前.说很菜吧,知道的还是不少.说精通吧,自我感觉还算不上. 认真的考虑下这个问题,觉得技术 ...