/**
* \file rsa.h
*
* \brief The RSA public-key cryptosystem
*
* Copyright (C) 2006-2010, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_RSA_H
#define POLARSSL_RSA_H

#include "bignum.h"

/*
* RSA Error codes
*/
#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */
#define POLARSSL_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */
#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */
#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the libraries validity check. */
#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */
#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */
#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */
#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */
#define POLARSSL_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */

/*
* PKCS#1 constants
*/
#define SIG_RSA_RAW 0
#define SIG_RSA_MD2 2
#define SIG_RSA_MD4 3
#define SIG_RSA_MD5 4
#define SIG_RSA_SHA1 5
#define SIG_RSA_SHA224 14
#define SIG_RSA_SHA256 11
#define SIG_RSA_SHA384 12
#define SIG_RSA_SHA512 13

#define RSA_PUBLIC 0
#define RSA_PRIVATE 1

#define RSA_PKCS_V15 0
#define RSA_PKCS_V21 1

#define RSA_SIGN 1
#define RSA_CRYPT 2

#define ASN1_STR_CONSTRUCTED_SEQUENCE "\x30"
#define ASN1_STR_NULL "\x05"
#define ASN1_STR_OID "\x06"
#define ASN1_STR_OCTET_STRING "\x04"

#define OID_DIGEST_ALG_MDX "\x2A\x86\x48\x86\xF7\x0D\x02\x00"
#define OID_HASH_ALG_SHA1 "\x2b\x0e\x03\x02\x1a"
#define OID_HASH_ALG_SHA2X "\x60\x86\x48\x01\x65\x03\x04\x02\x00"

#define OID_ISO_MEMBER_BODIES "\x2a"
#define OID_ISO_IDENTIFIED_ORG "\x2b"

/*
* ISO Member bodies OID parts
*/
#define OID_COUNTRY_US "\x86\x48"
#define OID_RSA_DATA_SECURITY "\x86\xf7\x0d"

/*
* ISO Identified organization OID parts
*/
#define OID_OIW_SECSIG_SHA1 "\x0e\x03\x02\x1a"

/*
* DigestInfo ::= SEQUENCE {
* digestAlgorithm DigestAlgorithmIdentifier,
* digest Digest }
*
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier
*
* Digest ::= OCTET STRING
*/
#define ASN1_HASH_MDX \
( \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x20" \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C" \
ASN1_STR_OID "\x08" \
OID_DIGEST_ALG_MDX \
ASN1_STR_NULL "\x00" \
ASN1_STR_OCTET_STRING "\x10" \
)

#define ASN1_HASH_SHA1 \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x21" \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x09" \
ASN1_STR_OID "\x05" \
OID_HASH_ALG_SHA1 \
ASN1_STR_NULL "\x00" \
ASN1_STR_OCTET_STRING "\x14"

#define ASN1_HASH_SHA1_ALT \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x1F" \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x07" \
ASN1_STR_OID "\x05" \
OID_HASH_ALG_SHA1 \
ASN1_STR_OCTET_STRING "\x14"

#define ASN1_HASH_SHA2X \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x11" \
ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d" \
ASN1_STR_OID "\x09" \
OID_HASH_ALG_SHA2X \
ASN1_STR_NULL "\x00" \
ASN1_STR_OCTET_STRING "\x00"

/**
* \brief RSA context structure
*/
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;

#ifdef __cplusplus
extern "C" {
#endif

/**
* \brief Initialize an RSA context
*
* \param ctx RSA context to be initialized
* \param padding RSA_PKCS_V15 or RSA_PKCS_V21
* \param hash_id RSA_PKCS_V21 hash identifier
*
* \note The hash_id parameter is actually ignored
* when using RSA_PKCS_V15 padding.
*/
void rsa_init( rsa_context *ctx,
int padding,
int hash_id);

/**
* \brief Generate an RSA keypair
*
* \param ctx RSA context that will hold the key
* \param f_rng RNG function
* \param p_rng RNG parameter
* \param nbits size of the public key in bits
* \param exponent public exponent (e.g., 65537)
*
* \note rsa_init() must be called beforehand to setup
* the RSA context.
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*/
int rsa_gen_key( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
unsigned int nbits, int exponent );

/**
* \brief Check a public RSA key
*
* \param ctx RSA context to be checked
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*/
int rsa_check_pubkey( const rsa_context *ctx );

/**
* \brief Check a private RSA key
*
* \param ctx RSA context to be checked
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*/
int rsa_check_privkey( const rsa_context *ctx );

/**
* \brief Do an RSA public key operation
*
* \param ctx RSA context
* \param input input buffer
* \param output output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note This function does NOT take care of message
* padding. Also, be sure to set input[0] = 0 or assure that
* input is smaller than N.
*
* \note The input and output buffers must be large
* enough (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_public( rsa_context *ctx,
const unsigned char *input,
unsigned char *output );

/**
* \brief Do an RSA private key operation
*
* \param ctx RSA context
* \param input input buffer
* \param output output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The input and output buffers must be large
* enough (eg. 128 bytes if RSA-1024 is used).
*/
int rsa_private( rsa_context *ctx,
const unsigned char *input,
unsigned char *output );

/**
* \brief Add the message padding, then do an RSA operation
*
* \param ctx RSA context
* \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding)
* \param p_rng RNG parameter
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param ilen contains the plaintext length
* \param input buffer holding the data to be encrypted
* \param output buffer that will hold the ciphertext
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
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 );

/**
* \brief Do an RSA operation, then remove the message padding
*
* \param ctx RSA context
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param olen will contain the plaintext length
* \param input buffer holding the encrypted data
* \param output buffer that will hold the plaintext
* \param output_max_len maximum length of the output buffer
*
* \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code
*
* \note The output buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
* an error is thrown.
*/
int rsa_pkcs1_decrypt( rsa_context *ctx,
int mode, size_t *olen,
const unsigned char *input,
unsigned char *output,
size_t output_max_len );

/**
* \brief Do a private RSA to sign a message digest
*
* \param ctx RSA context
* \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding)
* \param p_rng RNG parameter
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
* \param hashlen message digest length (for SIG_RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer that will hold the ciphertext
*
* \return 0 if the signing operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*
* \note In case of PKCS#1 v2.1 encoding keep in mind that
* the hash_id in the RSA context is the one used for the
* encoding. hash_id in the function call is the type of hash
* that is encoded. According to RFC 3447 it is advised to
* keep both hashes the same.
*/
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 );

/**
* \brief Do a public RSA and check the message digest
*
* \param ctx points to an RSA public key
* \param mode RSA_PUBLIC or RSA_PRIVATE
* \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
* \param hashlen message digest length (for SIG_RSA_RAW only)
* \param hash buffer holding the message digest
* \param sig buffer holding the ciphertext
*
* \return 0 if the verify operation was successful,
* or an POLARSSL_ERR_RSA_XXX error code
*
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*
* \note In case of PKCS#1 v2.1 encoding keep in mind that
* the hash_id in the RSA context is the one used for the
* verification. hash_id in the function call is the type of hash
* that is verified. According to RFC 3447 it is advised to
* keep both hashes the same.
*/
int rsa_pkcs1_verify( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig );

/**
* \brief Free the components of an RSA key
*
* \param ctx RSA Context to free
*/
void rsa_free( rsa_context *ctx );

/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int rsa_self_test( int verbose );

#ifdef __cplusplus
}
#endif

#endif /* rsa.h */

/*
* The RSA public-key cryptosystem
*
* Copyright (C) 2006-2011, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
*
* http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
* http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
*/

#include "polarssl/config.h"

#if defined(POLARSSL_RSA_C)

#include "polarssl/rsa.h"
#include "polarssl/md.h"

#include <stdlib.h>
#include <stdio.h>

/*
* Initialize an RSA context
*/
void rsa_init( rsa_context *ctx,
int padding,
int hash_id )
{
memset( ctx, 0, sizeof( rsa_context ) );

ctx->padding = padding;
ctx->hash_id = hash_id;
}

#if defined(POLARSSL_GENPRIME)

/*
* Generate an RSA keypair
*/
int rsa_gen_key( rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
unsigned int nbits, int exponent )
{
int ret;
mpi P1, Q1, H, G;

if( f_rng == NULL || nbits < 128 || exponent < 3 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &G );

/*
* find primes P and Q with Q < P so that:
* GCD( E, (P-1)*(Q-1) ) == 1
*/
MPI_CHK( mpi_lset( &ctx->E, exponent ) );

do
{
MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
f_rng, p_rng ) );

MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
f_rng, p_rng ) );

if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
mpi_swap( &ctx->P, &ctx->Q );

if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
continue;

MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
if( mpi_msb( &ctx->N ) != nbits )
continue;

MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );
}
while( mpi_cmp_int( &G, 1 ) != 0 );

/*
* D = E^-1 mod ((P-1)*(Q-1))
* DP = D mod (P - 1)
* DQ = D mod (Q - 1)
* QP = Q^-1 mod P
*/
MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) );
MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );

ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;

cleanup:

mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &G );

if( ret != 0 )
{
rsa_free( ctx );
return( POLARSSL_ERR_RSA_KEY_GEN_FAILED + ret );
}

return( 0 );
}

#endif

/*
* Check a public RSA key
*/
int rsa_check_pubkey( const rsa_context *ctx )
{
if( !ctx->N.p || !ctx->E.p )
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );

if( ( ctx->N.p[0] & 1 ) == 0 ||
( ctx->E.p[0] & 1 ) == 0 )
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );

if( mpi_msb( &ctx->N ) < 128 ||
mpi_msb( &ctx->N ) > POLARSSL_MPI_MAX_BITS )
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );

if( mpi_msb( &ctx->E ) < 2 ||
mpi_msb( &ctx->E ) > 64 )
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );

return( 0 );
}

/*
* Check a private RSA key
*/
int rsa_check_privkey( const rsa_context *ctx )
{
int ret;
mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2;

if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
return( ret );

if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );

mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 );
mpi_init( &H ); mpi_init( &I ); mpi_init( &G ); mpi_init( &G2 );
mpi_init( &L1 ); mpi_init( &L2 );

MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) );

MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) );
MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) );
MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) );

/*
* Check for a valid PKCS1v2 private key
*/
if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 ||
mpi_cmp_int( &L2, 0 ) != 0 ||
mpi_cmp_int( &I, 1 ) != 0 ||
mpi_cmp_int( &G, 1 ) != 0 )
{
ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED;
}

cleanup:

mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 );
mpi_free( &H ); mpi_free( &I ); mpi_free( &G ); mpi_free( &G2 );
mpi_free( &L1 ); mpi_free( &L2 );

if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED )
return( ret );

if( ret != 0 )
return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret );

return( 0 );
}

/*
* Do an RSA public key operation
*/
int rsa_public( rsa_context *ctx,
const unsigned char *input,
unsigned char *output )
{
int ret;
size_t olen;
mpi T;

mpi_init( &T );

MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );

if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
{
mpi_free( &T );
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}

olen = ctx->len;
MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
MPI_CHK( mpi_write_binary( &T, output, olen ) );

cleanup:

mpi_free( &T );

if( ret != 0 )
return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret );

return( 0 );
}

/*
* Do an RSA private key operation
*/
int rsa_private( rsa_context *ctx,
const unsigned char *input,
unsigned char *output )
{
int ret;
size_t olen;
mpi T, T1, T2;

mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );

MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );

if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
{
mpi_free( &T );
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}

#if defined(POLARSSL_RSA_NO_CRT)
MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
#else
/*
* faster decryption using the CRT
*
* T1 = input ^ dP mod P
* T2 = input ^ dQ mod Q
*/
MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );

/*
* T = (T1 - T2) * (Q^-1 mod P) mod P
*/
MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );

/*
* output = T2 + T * Q
*/
MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
#endif

olen = ctx->len;
MPI_CHK( mpi_write_binary( &T, output, olen ) );

cleanup:

mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );

if( ret != 0 )
return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret );

return( 0 );
}

#if defined(POLARSSL_PKCS1_V21)
/**
* Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer.
*
* \param dst buffer to mask
* \param dlen length of destination buffer
* \param src source of the mask generation
* \param slen length of the source buffer
* \param md_ctx message digest context to use
*/
static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, size_t slen,
md_context_t *md_ctx )
{
unsigned char mask[POLARSSL_MD_MAX_SIZE];
unsigned char counter[4];
unsigned char *p;
unsigned int hlen;
size_t i, use_len;

memset( mask, 0, POLARSSL_MD_MAX_SIZE );
memset( counter, 0, 4 );

hlen = md_ctx->md_info->size;

// Generate and apply dbMask
//
p = dst;

while( dlen > 0 )
{
use_len = hlen;
if( dlen < hlen )
use_len = dlen;

md_starts( md_ctx );
md_update( md_ctx, src, slen );
md_update( md_ctx, counter, 4 );
md_finish( md_ctx, mask );

for( i = 0; i < use_len; ++i )
*p++ ^= mask[i];

counter[3]++;

dlen -= use_len;
}
}
#endif

/*
* Add the message padding, then do an RSA operation
*/
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 )
{
size_t nb_pad, olen;
int ret;
unsigned char *p = output;
#if defined(POLARSSL_PKCS1_V21)
unsigned int hlen;
const md_info_t *md_info;
md_context_t md_ctx;
#endif

olen = ctx->len;

if( f_rng == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

switch( ctx->padding )
{
case RSA_PKCS_V15:

if( olen < ilen + 11 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

nb_pad = olen - 3 - ilen;

*p++ = 0;
*p++ = RSA_CRYPT;

while( nb_pad-- > 0 )
{
int rng_dl = 100;

do {
ret = f_rng( p_rng, p, 1 );
} while( *p == 0 && --rng_dl && ret == 0 );

// Check if RNG failed to generate data
//
if( rng_dl == 0 || ret != 0)
return POLARSSL_ERR_RSA_RNG_FAILED + ret;

p++;
}
*p++ = 0;
memcpy( p, input, ilen );
break;

#if defined(POLARSSL_PKCS1_V21)
case RSA_PKCS_V21:

md_info = md_info_from_type( ctx->hash_id );
if( md_info == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

hlen = md_get_size( md_info );

if( olen < ilen + 2 * hlen + 2 || f_rng == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

memset( output, 0, olen );
memset( &md_ctx, 0, sizeof( md_context_t ) );

md_init_ctx( &md_ctx, md_info );

*p++ = 0;

// Generate a random octet string seed
//
if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 )
return( POLARSSL_ERR_RSA_RNG_FAILED + ret );

p += hlen;

// Construct DB
//
md( md_info, p, 0, p );
p += hlen;
p += olen - 2 * hlen - 2 - ilen;
*p++ = 1;
memcpy( p, input, ilen );

// maskedDB: Apply dbMask to DB
//
mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen,
&md_ctx );

// maskedSeed: Apply seedMask to seed
//
mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1,
&md_ctx );
break;
#endif

default:

return( POLARSSL_ERR_RSA_INVALID_PADDING );
}

return( ( mode == RSA_PUBLIC )
? rsa_public( ctx, output, output )
: rsa_private( ctx, output, output ) );
}

/*
* Do an RSA operation, then remove the message padding
*/
int rsa_pkcs1_decrypt( rsa_context *ctx,
int mode, size_t *olen,
const unsigned char *input,
unsigned char *output,
size_t output_max_len)
{
int ret;
size_t ilen;
unsigned char *p;
unsigned char buf[1024];
#if defined(POLARSSL_PKCS1_V21)
unsigned char lhash[POLARSSL_MD_MAX_SIZE];
unsigned int hlen;
const md_info_t *md_info;
md_context_t md_ctx;
#endif

ilen = ctx->len;

if( ilen < 16 || ilen > sizeof( buf ) )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

ret = ( mode == RSA_PUBLIC )
? rsa_public( ctx, input, buf )
: rsa_private( ctx, input, buf );

if( ret != 0 )
return( ret );

p = buf;

switch( ctx->padding )
{
case RSA_PKCS_V15:

if( *p++ != 0 || *p++ != RSA_CRYPT )
return( POLARSSL_ERR_RSA_INVALID_PADDING );

while( *p != 0 )
{
if( p >= buf + ilen - 1 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
p++;
}
p++;
break;

#if defined(POLARSSL_PKCS1_V21)
case RSA_PKCS_V21:

if( *p++ != 0 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );

md_info = md_info_from_type( ctx->hash_id );
if( md_info == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

hlen = md_get_size( md_info );
memset( &md_ctx, 0, sizeof( md_context_t ) );

md_init_ctx( &md_ctx, md_info );

// Generate lHash
//
md( md_info, lhash, 0, lhash );

// seed: Apply seedMask to maskedSeed
//
mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
&md_ctx );

// DB: Apply dbMask to maskedDB
//
mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
&md_ctx );

p += hlen;

// Check validity
//
if( memcmp( lhash, p, hlen ) != 0 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );

p += hlen;

while( *p == 0 && p < buf + ilen )
p++;

if( p == buf + ilen )
return( POLARSSL_ERR_RSA_INVALID_PADDING );

if( *p++ != 0x01 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );

break;
#endif

default:

return( POLARSSL_ERR_RSA_INVALID_PADDING );
}

if (ilen - (p - buf) > output_max_len)
return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );

*olen = ilen - (p - buf);
memcpy( output, p, *olen );

return( 0 );
}

/*
* Do an RSA operation to sign the message digest
*/
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 )
{
size_t nb_pad, olen;
unsigned char *p = sig;
#if defined(POLARSSL_PKCS1_V21)
unsigned char salt[POLARSSL_MD_MAX_SIZE];
unsigned int slen, hlen, offset = 0;
int ret;
size_t msb;
const md_info_t *md_info;
md_context_t md_ctx;
#else
(void) f_rng;
(void) p_rng;
#endif

olen = ctx->len;

switch( ctx->padding )
{
case RSA_PKCS_V15:

switch( hash_id )
{
case SIG_RSA_RAW:
nb_pad = olen - 3 - hashlen;
break;

case SIG_RSA_MD2:
case SIG_RSA_MD4:
case SIG_RSA_MD5:
nb_pad = olen - 3 - 34;
break;

case SIG_RSA_SHA1:
nb_pad = olen - 3 - 35;
break;

case SIG_RSA_SHA224:
nb_pad = olen - 3 - 47;
break;

case SIG_RSA_SHA256:
nb_pad = olen - 3 - 51;
break;

case SIG_RSA_SHA384:
nb_pad = olen - 3 - 67;
break;

case SIG_RSA_SHA512:
nb_pad = olen - 3 - 83;
break;

default:
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}

if( nb_pad < 8 )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

*p++ = 0;
*p++ = RSA_SIGN;
memset( p, 0xFF, nb_pad );
p += nb_pad;
*p++ = 0;

switch( hash_id )
{
case SIG_RSA_RAW:
memcpy( p, hash, hashlen );
break;

case SIG_RSA_MD2:
memcpy( p, ASN1_HASH_MDX, 18 );
memcpy( p + 18, hash, 16 );
p[13] = 2; break;

case SIG_RSA_MD4:
memcpy( p, ASN1_HASH_MDX, 18 );
memcpy( p + 18, hash, 16 );
p[13] = 4; break;

case SIG_RSA_MD5:
memcpy( p, ASN1_HASH_MDX, 18 );
memcpy( p + 18, hash, 16 );
p[13] = 5; break;

case SIG_RSA_SHA1:
memcpy( p, ASN1_HASH_SHA1, 15 );
memcpy( p + 15, hash, 20 );
break;

case SIG_RSA_SHA224:
memcpy( p, ASN1_HASH_SHA2X, 19 );
memcpy( p + 19, hash, 28 );
p[1] += 28; p[14] = 4; p[18] += 28; break;

case SIG_RSA_SHA256:
memcpy( p, ASN1_HASH_SHA2X, 19 );
memcpy( p + 19, hash, 32 );
p[1] += 32; p[14] = 1; p[18] += 32; break;

case SIG_RSA_SHA384:
memcpy( p, ASN1_HASH_SHA2X, 19 );
memcpy( p + 19, hash, 48 );
p[1] += 48; p[14] = 2; p[18] += 48; break;

case SIG_RSA_SHA512:
memcpy( p, ASN1_HASH_SHA2X, 19 );
memcpy( p + 19, hash, 64 );
p[1] += 64; p[14] = 3; p[18] += 64; break;

default:
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}

break;

#if defined(POLARSSL_PKCS1_V21)
case RSA_PKCS_V21:

if( f_rng == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

switch( hash_id )
{
case SIG_RSA_MD2:
case SIG_RSA_MD4:
case SIG_RSA_MD5:
hashlen = 16;
break;

case SIG_RSA_SHA1:
hashlen = 20;
break;

case SIG_RSA_SHA224:
hashlen = 28;
break;

case SIG_RSA_SHA256:
hashlen = 32;
break;

case SIG_RSA_SHA384:
hashlen = 48;
break;

case SIG_RSA_SHA512:
hashlen = 64;
break;

default:
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}

md_info = md_info_from_type( ctx->hash_id );
if( md_info == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

hlen = md_get_size( md_info );
slen = hlen;

memset( sig, 0, olen );
memset( &md_ctx, 0, sizeof( md_context_t ) );

md_init_ctx( &md_ctx, md_info );

msb = mpi_msb( &ctx->N ) - 1;

// Generate salt of length slen
//
if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
return( POLARSSL_ERR_RSA_RNG_FAILED + ret );

// Note: EMSA-PSS encoding is over the length of N - 1 bits
//
msb = mpi_msb( &ctx->N ) - 1;
p += olen - hlen * 2 - 2;
*p++ = 0x01;
memcpy( p, salt, slen );
p += slen;

// Generate H = Hash( M' )
//
md_starts( &md_ctx );
md_update( &md_ctx, p, 8 );
md_update( &md_ctx, hash, hashlen );
md_update( &md_ctx, salt, slen );
md_finish( &md_ctx, p );

// Compensate for boundary condition when applying mask
//
if( msb % 8 == 0 )
offset = 1;

// maskedDB: Apply dbMask to DB
//
mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx );

msb = mpi_msb( &ctx->N ) - 1;
sig[0] &= 0xFF >> ( olen * 8 - msb );

p += hlen;
*p++ = 0xBC;
break;
#endif

default:

return( POLARSSL_ERR_RSA_INVALID_PADDING );
}

return( ( mode == RSA_PUBLIC )
? rsa_public( ctx, sig, sig )
: rsa_private( ctx, sig, sig ) );
}

/*
* Do an RSA operation and check the message digest
*/
int rsa_pkcs1_verify( rsa_context *ctx,
int mode,
int hash_id,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig )
{
int ret;
size_t len, siglen;
unsigned char *p, c;
unsigned char buf[1024];
#if defined(POLARSSL_PKCS1_V21)
unsigned char result[POLARSSL_MD_MAX_SIZE];
unsigned char zeros[8];
unsigned int hlen;
size_t slen, msb;
const md_info_t *md_info;
md_context_t md_ctx;
#endif
siglen = ctx->len;

if( siglen < 16 || siglen > sizeof( buf ) )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

ret = ( mode == RSA_PUBLIC )
? rsa_public( ctx, sig, buf )
: rsa_private( ctx, sig, buf );

if( ret != 0 )
return( ret );

p = buf;

switch( ctx->padding )
{
case RSA_PKCS_V15:

if( *p++ != 0 || *p++ != RSA_SIGN )
return( POLARSSL_ERR_RSA_INVALID_PADDING );

while( *p != 0 )
{
if( p >= buf + siglen - 1 || *p != 0xFF )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
p++;
}
p++;

len = siglen - ( p - buf );

if( len == 33 && hash_id == SIG_RSA_SHA1 )
{
if( memcmp( p, ASN1_HASH_SHA1_ALT, 13 ) == 0 &&
memcmp( p + 13, hash, 20 ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
if( len == 34 )
{
c = p[13];
p[13] = 0;

if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
return( POLARSSL_ERR_RSA_VERIFY_FAILED );

if( ( c == 2 && hash_id == SIG_RSA_MD2 ) ||
( c == 4 && hash_id == SIG_RSA_MD4 ) ||
( c == 5 && hash_id == SIG_RSA_MD5 ) )
{
if( memcmp( p + 18, hash, 16 ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
}

if( len == 35 && hash_id == SIG_RSA_SHA1 )
{
if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
memcmp( p + 15, hash, 20 ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}
if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) ||
( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) ||
( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) ||
( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) )
{
c = p[1] - 17;
p[1] = 17;
p[14] = 0;

if( p[18] == c &&
memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 &&
memcmp( p + 19, hash, c ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}

if( len == hashlen && hash_id == SIG_RSA_RAW )
{
if( memcmp( p, hash, hashlen ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
}

break;

#if defined(POLARSSL_PKCS1_V21)
case RSA_PKCS_V21:

if( buf[siglen - 1] != 0xBC )
return( POLARSSL_ERR_RSA_INVALID_PADDING );

switch( hash_id )
{
case SIG_RSA_MD2:
case SIG_RSA_MD4:
case SIG_RSA_MD5:
hashlen = 16;
break;

case SIG_RSA_SHA1:
hashlen = 20;
break;

case SIG_RSA_SHA224:
hashlen = 28;
break;

case SIG_RSA_SHA256:
hashlen = 32;
break;

case SIG_RSA_SHA384:
hashlen = 48;
break;

case SIG_RSA_SHA512:
hashlen = 64;
break;

default:
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
}

md_info = md_info_from_type( ctx->hash_id );
if( md_info == NULL )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

hlen = md_get_size( md_info );
slen = siglen - hlen - 1;

memset( &md_ctx, 0, sizeof( md_context_t ) );
memset( zeros, 0, 8 );

md_init_ctx( &md_ctx, md_info );

// Note: EMSA-PSS verification is over the length of N - 1 bits
//
msb = mpi_msb( &ctx->N ) - 1;

// Compensate for boundary condition when applying mask
//
if( msb % 8 == 0 )
{
p++;
siglen -= 1;
}
if( buf[0] >> ( 8 - siglen * 8 + msb ) )
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx );

buf[0] &= 0xFF >> ( siglen * 8 - msb );

while( *p == 0 && p < buf + siglen )
p++;

if( p == buf + siglen )
return( POLARSSL_ERR_RSA_INVALID_PADDING );

if( *p++ != 0x01 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );

slen -= p - buf;

// Generate H = Hash( M' )
//
md_starts( &md_ctx );
md_update( &md_ctx, zeros, 8 );
md_update( &md_ctx, hash, hashlen );
md_update( &md_ctx, p, slen );
md_finish( &md_ctx, result );

if( memcmp( p + slen, result, hlen ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
#endif

default:

return( POLARSSL_ERR_RSA_INVALID_PADDING );
}

return( POLARSSL_ERR_RSA_INVALID_PADDING );
}

/*
* Free the components of an RSA key
*/
void rsa_free( rsa_context *ctx )
{
mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN );
mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP );
mpi_free( &ctx->Q ); mpi_free( &ctx->P ); mpi_free( &ctx->D );
mpi_free( &ctx->E ); mpi_free( &ctx->N );
}

#if defined(POLARSSL_SELF_TEST)

#include "polarssl/sha1.h"

/*
* Example RSA-1024 keypair, for test purposes
*/
#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 24
#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
"\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"

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

if( verbose != 0 )
printf( " RSA key validation: " );

if( rsa_check_pubkey( &rsa ) != 0 ||
rsa_check_privkey( &rsa ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );

return( 1 );
}

if( verbose != 0 )
printf( "passed\n PKCS#1 encryption : " );

memcpy( rsa_plaintext, RSA_PT, PT_LEN );

if( rsa_pkcs1_encrypt( &rsa, &myrand, NULL, RSA_PUBLIC, PT_LEN,
rsa_plaintext, rsa_ciphertext ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );

return( 1 );
}

if( verbose != 0 )
printf( "passed\n PKCS#1 decryption : " );

if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len,
rsa_ciphertext, rsa_decrypted,
sizeof(rsa_decrypted) ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );

return( 1 );
}

if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );

return( 1 );
}

#if defined(POLARSSL_SHA1_C)
if( verbose != 0 )
printf( "passed\n 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\n" );

return( 1 );
}

if( verbose != 0 )
printf( "passed\n PKCS#1 sig. verify: " );

if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20,
sha1sum, rsa_ciphertext ) != 0 )
{
if( verbose != 0 )
printf( "failed\n" );

return( 1 );
}

if( verbose != 0 )
printf( "passed\n\n" );
#endif /* POLARSSL_SHA1_C */

rsa_free( &rsa );

return( 0 );
}

#endif

#endif

RSA加密(C语言)的更多相关文章

  1. openssl C语言编码实现rsa加密

    非原创, 引用自: 1 CC=gcc CPPFLAGS= -I /home/yyx//openssl-1.0.1t/include/ CFLAGS=-Wall -g LIBPATH = -L /usr ...

  2. Jmeter_前端RSA加密下的登陆模拟_引用js文件实现

    版权声明:本文为博主原创文章,未经博主允许不得转载. 在一次项目实战中,前端登录使用了RSA加密,使用LoadRunner压测的第一步,就是模拟用户登录,可惜loadRunner11并不能录制前端的加 ...

  3. Jmeter_前端RSA加密下的登陆模拟_引用js文件实现(转)

    在一次项目实战中,前端登录使用了RSA加密,使用LoadRunner压测的第一步,就是模拟用户登录,可惜loadRunner11并不能录制前端的加密过程,并且安装的LR是基于C语言版,网络上关于RSA ...

  4. python实现RSA加密和签名以及分段加解密的方案

    1.前言 很多朋友在工作中,会遇到一些接口使用RSA加密和签名来处理的请求参数,那么遇到这个问题的时候,第一时间当然是找开发要加解密的方法,但是开发给加解密代码,大多数情况都是java,c++,js等 ...

  5. python RSA加密、解密、签名

    python RSA加密.解密.签名 python中用于RSA加解密的库有好久个,本文主要讲解rsa.M2Crypto.Crypto这三个库对于RSA加密.解密.签名.验签的知识点. 知识基础 加密是 ...

  6. RSA加密原理与秘钥、公钥生成

    RSA加密(非对称加密) RSA公开密钥密码体制.所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制.(不可逆向运算的加密方法) ...

  7. MD5,Des,RSA加密解密

    一.加密和解密 下面先熟悉几个概念 1>对称加密:加密的key和解密的key是同一个 但是如何确保密钥安全地进行传递?秘钥的安全是一个问题 2>非对称加密:加密点的key和解密的key不是 ...

  8. “不给力啊,老湿!”:RSA加密与破解

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 加密和解密是自古就有技术了.经常看到侦探电影的桥段,勇敢又机智的主角,拿着一长串毫 ...

  9. .NET 对接JAVA 使用Modulus,Exponent RSA 加密

    最近有一个工作是需要把数据用RSA发送给Java 虽然一开始标准公钥 net和Java  RSA填充的一些算法不一样 但是后来这个坑也补的差不多了 具体可以参考 http://www.cnblogs. ...

随机推荐

  1. 让C#可以像Javascript一样操作Json

    Json的简介 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. JSON采用完全独立于语言的文本格式,但是也使用了 ...

  2. Windows phone应用开发[21]-图片性能优化

    在windows phone 中常在列表中会常包含比较丰富文字和图片混排数据信息. 针对列表数据中除了谈到listbox等控件自身数据虚拟化问题外.虽然wp硬件设备随着SDK 8.0 发布得到应用可使 ...

  3. 【jQuery】 jQuery上下飘动效果

    jQuery实现图片上下飘动效果 function moveRocket() { $(".smallShip") //2000毫秒内top = top + 60: .animate ...

  4. 使用属性动画 — Property Animation

    属性动画,就是通过控制对象中的属性值产生的动画.属性动画是目前最高级的2D动画系统. 在API Level 11中添加.Property Animation号称能控制一切对象的动画,包括可见的和不可见 ...

  5. hibernate的三表查询

    表的关系: Cardgraderule      1:n     Cardgrade Cardgrade           1:n     Acardtype 实体类: public class C ...

  6. Asp.Net MVC<九>:OWIN,关于StartUp.cs

    https://msdn.microsoft.com/zh-cn/magazine/dn451439.aspx(Katana 项目入门) 一不小心写了个WEB服务器 快刀斩乱麻之 Katana OWI ...

  7. bzoj4199:NOI2015D2T2品酒大会(SAM版)

    SAM感觉写起来比SA更直观(?) #include <iostream> #include <cstdio> #include <cstring> #includ ...

  8. iOS开发UI篇—懒加载

    iOS开发UI篇—懒加载 1.懒加载基本 懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了, ...

  9. JS中匿名函数$(function(){ })和(function(){})()的区别

    “$(function(){ });” Jquery语法的匿名函数,用于存放操作DOM对象的代码,执行其中代码时DOM对象已存在: (通过这样就可以在页面加载完成时通过ajax再异步加载一些数据) “ ...

  10. 树莓派笔记之使用netselect选择最快Raspbian软件源

    背景: 之前在葉難大大的部落格里看到有讲可以使用netselect查找最快软件源,今天正好看到, 特此记下来,因为之前一直使用中国科学技术大学的源,结果发现不是我这里最快的. 注意: 以下仅对Rasp ...