📄 ssh2_cry.c
字号:
/****************************************************************************
* *
* cryptlib SSHv2 Crypto Routines *
* Copyright Peter Gutmann 1998-2008 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "misc_rw.h"
#include "session.h"
#include "ssh.h"
#else
#include "crypt.h"
#include "misc/misc_rw.h"
#include "session/session.h"
#include "session/ssh.h"
#endif /* Compiler-specific includes */
#ifdef USE_SSH
/****************************************************************************
* *
* Key Load/Init Functions *
* *
****************************************************************************/
/* Load the fixed SSHv2 DH key into a context. The prime is the value
2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }, from the Oakley spec
(RFC 2412, other locations omit the q value). Unfortunately the choice
of q leads to horribly inefficient operations since it's 860 bits larger
than it needs to be */
static const BYTE FAR_BSS dh1024SPKI[] = {
0x30, 0x82, 0x01, 0xA2,
0x30, 0x82, 0x01, 0x17,
0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3E, 0x02, 0x01,
0x30, 0x82, 0x01, 0x0A,
0x02, 0x81, 0x81, 0x00, /* p */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x02, 0x01, /* g */
0x02,
0x02, 0x81, 0x80, /* q */
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A,
0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68,
0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A,
0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91,
0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E,
0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D,
0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B,
0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22,
0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63,
0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5,
0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6,
0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2,
0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3,
0x24, 0x94, 0x33, 0x28, 0xF6, 0x73, 0x29, 0xC0,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x03, 0x81, 0x84, 0x00,
0x02, 0x81, 0x80, /* y (dummy value for key-read code) */
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x44, 0x6F, 0x65, 0x73, 0x20, 0x79, 0x6F, 0x75,
0x72, 0x20, 0x6D, 0x6F, 0x74, 0x68, 0x65, 0x72,
0x20, 0x6B, 0x6E, 0x6F, 0x77, 0x20, 0x79, 0x6F,
0x75, 0x27, 0x72, 0x65, 0x20, 0x64, 0x6F, 0x69,
0x6E, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x3F,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Additional DH values, from RFC 3526. The 1536-bit value is widely used
in IKE, and has the prime value
2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 }. The 2048-bit
value has the prime value
2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }, and the 3072-bit
value has the prime value
2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 }. All have a
generator of 2 */
static const BYTE FAR_BSS dh1536SSH[] = {
0x00, 0x00, 0x00, 0xD8,
0x00, 0x00, 0x00, 0x06, /* Algorithm ID */
's', 's', 'h', '-', 'd', 'h',
0x00, 0x00, 0x00, 0xC1, /* p */
0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x01, /* g */
0x02
};
static const BYTE FAR_BSS dh2048SSH[] = {
0x00, 0x00, 0x01, 0x18,
0x00, 0x00, 0x00, 0x06, /* Algorithm ID */
's', 's', 'h', '-', 'd', 'h',
0x00, 0x00, 0x01, 0x01, /* p */
0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x01, /* g */
0x02
};
static const BYTE FAR_BSS dh3072SSH[] = {
0x00, 0x00, 0x01, 0x98,
0x00, 0x00, 0x00, 0x06, /* Algorithm ID */
's', 's', 'h', '-', 'd', 'h',
0x00, 0x00, 0x01, 0x81, /* p */
0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x01, /* g */
0x02
};
int initDHcontextSSH( CRYPT_CONTEXT *iCryptContext, int *keySize,
const void *keyData, const int keyDataLength,
const int requestedKeySize )
{
CRYPT_CONTEXT iDHContext;
MESSAGE_CREATEOBJECT_INFO createInfo;
MESSAGE_DATA msgData;
int keyType = CRYPT_IATTRIBUTE_KEY_SSH, keyLength = keyDataLength;
int length = DUMMY_INIT, status;
assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
assert( isWritePtr( keySize, sizeof( int ) ) );
assert( ( isReadPtr( keyData, keyDataLength ) && \
requestedKeySize == CRYPT_UNUSED ) || \
( keyData == NULL && keyDataLength == 0 && \
requestedKeySize == CRYPT_USE_DEFAULT ) || \
( keyData == NULL && keyDataLength == 0 && \
requestedKeySize >= MIN_PKCSIZE && \
requestedKeySize <= CRYPT_MAX_PKCSIZE ) );
/* Clear return values */
*iCryptContext = CRYPT_ERROR;
*keySize = 0;
/* Create the DH context to contain the key */
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_DH );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( status );
iDHContext = createInfo.cryptHandle;
setMessageData( &msgData, "SSH DH key", 10 );
status = krnlSendMessage( iDHContext, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_LABEL );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iDHContext, IMESSAGE_DECREFCOUNT );
return( status );
}
/* If we're not being given externally-supplied DH key components, get
the actual key size based on the requested key size. The spec
requires that we use the smallest key size that's larger than the
requested one, we allow for a small amount of slop to ensure that we
don't scale up to some huge key size if the client's keysize
calculation is off by a few bits */
if( keyData == NULL )
{
const int actualKeySize = \
( requestedKeySize == CRYPT_USE_DEFAULT ) ? SSH2_DEFAULT_KEYSIZE : \
( requestedKeySize < 128 + 8 ) ? bitsToBytes( 1024 ) : \
( requestedKeySize < 192 + 8 ) ? bitsToBytes( 1536 ) : \
( requestedKeySize < 256 + 8 ) ? bitsToBytes( 2048 ) : \
( requestedKeySize < 384 + 8 ) ? bitsToBytes( 3072 ) : \
0;
/* If the requested key size corresponds (at least approximately) to
a built-in DH value, load the built-in key value, otherwise
generate a new one. In theory we should probably generate a new
DH key each time:
status = krnlSendMessage( iDHContext, IMESSAGE_SETATTRIBUTE,
( void * ) &requestedKeySize,
CRYPT_CTXINFO_KEYSIZE );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iDHContext, IMESSAGE_CTX_GENKEY,
NULL, FALSE );
however because the handshake is set up so that the client (rather
than the server) chooses the key size, we can't actually perform
the generation until we're in the middle of the handshake. This
means that the server will grind to a halt during each handshake
as it generates a new key of whatever size takes the client's
fancy (it also leads to a nice potential DoS attack on the
server). To avoid this problem, we use fixed keys of various
common sizes */
switch( actualKeySize )
{
case bitsToBytes( 1024 ):
keyData = dh1024SPKI;
keyLength = sizeof( dh1024SPKI );
keyType = CRYPT_IATTRIBUTE_KEY_SPKI;
break;
case bitsToBytes( 1536 ):
keyData = dh1536SSH,
keyLength = sizeof( dh1536SSH );
break;
case bitsToBytes( 2048 ):
keyData = dh2048SSH,
keyLength = sizeof( dh2048SSH );
break;
case bitsToBytes( 3072 ):
default: /* Hier ist der mast zu ende */
keyData = dh3072SSH,
keyLength = sizeof( dh3072SSH );
break;
}
}
setMessageData( &msgData, ( void * ) keyData, keyLength );
status = krnlSendMessage( iDHContext, IMESSAGE_SETATTRIBUTE_S, &msgData,
keyType );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iDHContext, IMESSAGE_GETATTRIBUTE,
&length, CRYPT_CTXINFO_KEYSIZE );
if( cryptStatusError( status ) )
{
assert( DEBUG_WARN );
krnlSendNotifier( iDHContext, IMESSAGE_DECREFCOUNT );
return( status );
}
*iCryptContext = iDHContext;
*keySize = length;
return( CRYPT_OK );
}
/* Complete the hashing necessary to generate a cryptovariable and send it
to a context */
static int loadCryptovariable( const CRYPT_CONTEXT iCryptContext,
const CRYPT_ATTRIBUTE_TYPE attribute,
const int attributeSize, HASHFUNCTION hashFunction,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -