polarsslのRSA使用

11869 ワード

PlarSSLソースは、最もコンパクトなsslコードライブラリです.効率的で、移植と統合が容易です.特に組み込みアプリケーションに適しています.PlarSSLには対応するpem形式はなく,ベースの復号化方法のみである.
RSA関連API
1.基本データ構造
typedef struct
{
    int ver;                    /*!<  always 0          */
    size_t len;                 /*!<  size(N) in chars  */

    mpi N;                      /*!<  public modulus    */
    mpi E;                      /*!<  public exponent   */

    mpi D;                      /*!<  private exponent  */
    mpi P;                      /*!<  1st prime factor  */
    mpi Q;                      /*!<  2nd prime factor  */
    mpi DP;                     /*!<  D % (P - 1)       */
    mpi DQ;                     /*!<  D % (Q - 1)       */
    mpi QP;                     /*!<  1 / (Q % P)       */

    mpi RN;                     /*!<  cached R^2 mod N  */
    mpi RP;                     /*!<  cached R^2 mod P  */
    mpi RQ;                     /*!<  cached R^2 mod Q  */

    int padding;                /*!<  RSA_PKCS_V15 for 1.5 padding and
                                      RSA_PKCS_v21 for OAEP/PSS         */
    int hash_id;                /*!<  Hash identifier of md_type_t as
                                      specified in the md.h header file
                                      for the EME-OAEP and EMSA-PSS
                                      encoding                          */
}
rsa_context;

2.mpiユニット
//     mpi  
void mpi_init( mpi *X );
//    mpi
void mpi_free( mpi *X );
//    mpi  
int mpi_grow( mpi *X, size_t nblimbs );
//    mpi    
int mpi_copy( mpi *X, const mpi *Y );
//    mpi    
void mpi_swap( mpi *X, mpi *Y );
//  int  mpi  
int mpi_lset( mpi *X, t_sint z );
//  mpi  
int mpi_get_bit( const mpi *X, size_t pos );
//   0  mpi    
size_t mpi_lsb( const mpi *X );
//  mpi    
size_t mpi_msb( const mpi *X );
//  mpi   
size_t mpi_size( const mpi *X );
//      mpi 
int mpi_read_string( mpi *X, int radix, const char *s );
//  mpi    
int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen );

3.RSA鍵管理
//   rsa   ,  padding, padding==RSA_PKCS_V15,hash_id   
void rsa_init( rsa_context *ctx, int padding, int hash_id);
//  rsa   
int rsa_gen_key( rsa_context *ctx,
                 int (*f_rng)(void *, unsigned char *, size_t),
                 void *p_rng,
                 unsigned int nbits, int exponent );
//      
int rsa_check_pubkey( const rsa_context *ctx );
//      
int rsa_check_privkey( const rsa_context *ctx );

3.RSA復号化
/*   PKCS#1    
 * \param ctx     RSA   
 * \param f_rng          
 * \param p_rng            
 * \param mode        RSA_PUBLIC   RSA_PRIVATE
 * \param ilen        
 * \param input         
 * \param output         
 *
 * \return         0    
*/
int rsa_pkcs1_encrypt( rsa_context *ctx,
                       int (*f_rng)(void *, unsigned char *, size_t),
                       void *p_rng,
                       int mode, size_t ilen,
                       const unsigned char *input,
                       unsigned char *output );
/*     
 * \param ctx      RSA   
 * \param mode     RSA_PUBLIC  RSA_PRIVATE
 * \param olen              
 * \param input        
 * \param output          
 * \param output_max_len               
 *
 * \return         0    
*/
int rsa_pkcs1_decrypt( rsa_context *ctx,
                       int mode, size_t *olen,
                       const unsigned char *input,
                       unsigned char *output,
                       size_t output_max_len );

4.RSA署名とチェック
/**   PKCS#1  ,  rsa            
 * \param ctx      RSA   
 * \param f_rng           
 * \param p_rng             
 * \param mode     RSA_PUBLIC RSA_PRIVATE
 * \param hash_id      SIG_RSA_RAW, SIG_RSA_MD{2,4,5} SIG_RSA_SHA{1,224,256,384,512}
 * \param hashlen        
 * \param hash           
 * \param sig                
 *
 * \return         0    
*/
int rsa_pkcs1_sign( rsa_context *ctx,
                    int (*f_rng)(void *, unsigned char *, size_t),
                    void *p_rng,
                    int mode,
                    int hash_id,
                    unsigned int hashlen,
                    const unsigned char *hash,
                    unsigned char *sig );

/**   PKCS#1  ,          
 * \param ctx      rsa  
 * \param mode     RSA_PUBLIC   RSA_PRIVATE
 * \param hash_id      SIG_RSA_RAW, SIG_RSA_MD{2,4,5}  SIG_RSA_SHA{1,224,256,384,512}
 * \param hashlen        
 * \param hash         
 * \param sig              
 *
 * \return         0    
 */
int rsa_pkcs1_verify( rsa_context *ctx,
                      int mode,
                      int hash_id,
                      unsigned int hashlen,
                      const unsigned char *hash,
                      unsigned char *sig );

RSAプログラミング例
#define KEY_LEN 128

#define RSA_N   "9292758453063D803DD603D5E777D788" \
                "8ED1D5BF35786190FA2F23EBC0848AEA" \
                "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
                "7130B9CED7ACDF54CFC7555AC14EEBAB" \
                "93A89813FBF3C4F8066D2D800F7C38A8" \
                "1AE31942917403FF4946B0A83D3D3E05" \
                "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
                "5E94BB77B07507233A0BC7BAC8F90F79"

#define RSA_E   "10001"

#define RSA_D   "24BF6185468786FDD303083D25E64EFC" \
                "66CA472BC44D253102F8B4A9D3BFA750" \
                "91386C0077937FE33FA3252D28855837" \
                "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
                "DF79C5CE07EE72C7F123142198164234" \
                "CABB724CF78B8173B9F880FC86322407" \
                "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
                "071513A1E85B5DFA031F21ECAE91A34D"

#define RSA_P   "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
                "2C01CAD19EA484A87EA4377637E75500" \
                "FCB2005C5C7DD6EC4AC023CDA285D796" \
                "C3D9E75E1EFC42488BB4F1D13AC30A57"

#define RSA_Q   "C000DF51A7C77AE8D7C7370C1FF55B69" \
                "E211C2B9E5DB1ED0BF61D0D9899620F4" \
                "910E4168387E3C30AA1E00C339A79508" \
                "8452DD96A9A5EA5D9DCA68DA636032AF"

#define RSA_DP  "C1ACF567564274FB07A0BBAD5D26E298" \
                "3C94D22288ACD763FD8E5600ED4A702D" \
                "F84198A5F06C2E72236AE490C93F07F8" \
                "3CC559CD27BC2D1CA488811730BB5725"

#define RSA_DQ  "4959CBF6F8FEF750AEE6977C155579C7" \
                "D8AAEA56749EA28623272E4F7D0592AF" \
                "7C1F1313CAC9471B5C523BFE592F517B" \
                "407A1BD76C164B93DA2D32A383E58357"

#define RSA_QP  "9AE7FBC99546432DF71896FC239EADAE" \
                "F38D18D2B2F0E2DD275AA977E2BF4411" \
                "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
                "A74206CEC169D74BF5A8C50D6F48EA08"

#define PT_LEN  10
#define RSA_PT  "helo rsa"

static int myrand(void *rng_state, unsigned char *output, size_t len) {
    size_t i;

    if (rng_state != NULL)
        rng_state = NULL;

    for (i = 0; i < len; ++i)
        output[i] = rand();

    return (0);
}

/*
 * Checkup routine
 */
int rsa_self_test(int verbose) {
    size_t len;
    rsa_context rsa;
    unsigned char rsa_plaintext[PT_LEN];
    unsigned char rsa_decrypted[PT_LEN];
    unsigned char rsa_ciphertext[KEY_LEN];
#if defined(POLARSSL_SHA1_C)
    unsigned char sha1sum[20];
#endif

    rsa_init(&rsa, RSA_PKCS_V15, 0);

    rsa.len = KEY_LEN;
    mpi_read_string(&rsa.N, 16, RSA_N);
    mpi_read_string(&rsa.E, 16, RSA_E);
    mpi_read_string(&rsa.D, 16, RSA_D);
    mpi_read_string(&rsa.P, 16, RSA_P);
    mpi_read_string(&rsa.Q, 16, RSA_Q);
    mpi_read_string(&rsa.DP, 16, RSA_DP);
    mpi_read_string(&rsa.DQ, 16, RSA_DQ);
    mpi_read_string(&rsa.QP, 16, RSA_QP);

    printf("RSA Test
"); if (verbose != 0) printf(" RSA key validation: "); if (rsa_check_pubkey(&rsa) != 0 || rsa_check_privkey(&rsa) != 0) { if (verbose != 0) printf("failed
"); return (1); } memcpy(rsa_plaintext, RSA_PT, PT_LEN); printf("
:%s
", rsa_plaintext); if (verbose != 0) printf("passed
PKCS#1 encryption : "); if (rsa_pkcs1_encrypt(&rsa, &myrand, NULL, RSA_PUBLIC, PT_LEN, rsa_plaintext, rsa_ciphertext) != 0) { if (verbose != 0) printf("failed
"); return (1); } if (verbose != 0) printf("passed
PKCS#1 decryption : "); if (rsa_pkcs1_decrypt(&rsa, RSA_PRIVATE, &len, rsa_ciphertext, rsa_decrypted, sizeof(rsa_decrypted)) != 0) { if (verbose != 0) printf("failed
"); return (1); } if (memcmp(rsa_decrypted, rsa_plaintext, len) != 0) { if (verbose != 0) printf("failed
"); return (1); } printf("
:%s
", rsa_decrypted); #if defined(POLARSSL_SHA1_C) if (verbose != 0) printf("passed
PKCS#1 data sign : "); sha1(rsa_plaintext, PT_LEN, sha1sum); if (rsa_pkcs1_sign(&rsa, NULL, NULL, RSA_PRIVATE, SIG_RSA_SHA1, 20, sha1sum, rsa_ciphertext) != 0) { if (verbose != 0) printf("failed
"); return (1); } if (verbose != 0) printf("passed
PKCS#1 sig. verify: "); if (rsa_pkcs1_verify(&rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20, sha1sum, rsa_ciphertext) != 0) { if (verbose != 0) printf("failed
"); return (1); } if (verbose != 0) printf("passed

"); #endif /* POLARSSL_SHA1_C */ rsa_free(&rsa); return (0); }

出力された結果は次のとおりです.
RSA Test
  RSA key validation: 
      :helo rsa 
passed
  PKCS#1 encryption : passed
  PKCS#1 decryption : 
      :helo rsa 
passed
  PKCS#1 data sign  : passed
  PKCS#1 sig. verify: passed

秘密鍵pemを取得する場合の検証プログラムのデバッグ方法
1.公開鍵暗号化を検証し、秘密鍵復号使用プログラムは文字列:helo rsaフィールドを暗号化し、暗号化後base 64符号化に変換する.結果:
   :
helo rsa
   :
NogGOEbfZ7YZn1G+8GO82MPXxWVYO964187G1ZhdYq1bS3Lvit2IRP66UFY9/ffSW2Ck1HN0BQ/mhwkTQRWnmdvby15amOnV6/XABEYAz0156ai1klpocCoFNqHwwO498gp3tSUUW0ULPgpPtXdWK8jkNAgALhasg7wHKXOk1p/xgSWtDPj+7LqZ45ooKCcA+xMbMXeYH1hs0zsFzp842rVWAThj5TBIhG0xfY80hKPrsAXDiOe19OUJf0+uZbSrI/so3yiI2mnosgfq12Srw5JFl9X3wDI+lKA3xOO1dcDYNbfpacPzaRRz/vxr0ZJJ67Uc5i+48/BFqTUPc+dcUw==

符号化ファイルはrsa_encrypt_encode.txtファイルに格納される.(1)base 64復号動作
base64 -d rsa_encrypt_encode.txt > rsa_encrypt.txt

(2)秘密鍵の復号
openssl rsautl -decrypt -in rsa_encrypt.txt -inkey rsa_pri.key -out rsa_decrypt.txt

結果:helo rsa2.検証公開鍵チェックは、まずファイルの要約を取得し、長さは40文字である.
$ openssl dgst -sha1 file.txt
SHA1(file.txt)= 52b60977ce28dd6c0c6f096f722d9d9fbaba0dd5

次に、ファイルの概要に署名します.
$ openssl dgst -sha1 -sign rsa_pri_2048.key -out sign_file.txt file.txt

署名されたファイルをbase 64符号化します.
$ base64 sign_file.txt > sign_file_base64.txt

次に、コード公開鍵を使用してチェックアウトを行います.
3.秘密鍵暗号化、公開鍵復号はまずファイルを暗号化する:
$ openssl rsautl -encrypt -in rsa_decrypt.txt -inkey rsa_pri_2048.pem -out rsa_encrypt.txt

次に、暗号化されたファイルをbase 64符号化します.
$ base64 rsa_encrypt.txt > rsa_encrypt_base64.txt

その後、コード公開鍵を使用して復号化される.