Давайте посмотрим на реализацию различных алгоритмов шифрования в Node.js.

Node.js
Давайте посмотрим на реализацию различных алгоритмов шифрования в Node.js.

В соответствии с тенденцией большого фронтенда, фронтендер также должен знать некоторые знания о шифровании данных.Нам не нужно изучать реализацию и принцип алгоритма шифрования.В конце концов,шифрование-это продвинутый предмет, но базовый метод шифровки и кодирования еще надо я освоил, в конце концов, я никогда не ел свинины, и я видел ее раньше.

Я резюмирую несколько распространенных алгоритмов шифрования и подписи и прикрепляюnodejsреализация кодировки.

Алгоритм шифрования

Для обеспечения безопасности данных и защиты от несанкционированного доступа многие данные при передаче шифруются. Как каштан на сцене, многие веб-сайты недавно были обновлены доhttpsпротокол,httpsПротокол использует асимметричное шифрование и хэш-подписи, а такжеgithubв использованииssh, что также является асимметричным шифрованием. И большинство паролей, используемых при входе в системуMD5шифрование и др.

Шифрование можно разделить на три категории, симметричное шифрование и асимметричное шифрование, а также алгоритмы дайджеста, мы будем расширять их один за другим.

Симметричное шифрование

Цитирую описание из Википедии:

Используя метод шифрования криптосистемы с одним ключом, один и тот же ключ может использоваться для одновременного шифрования и расшифровки информации.Этот метод шифрования называется симметричным шифрованием, также известным как шифрование с одним ключом.

Симметричное шифрование легко понять, так же, как я даю вам ключ от моего дома, если вы хотите прийти в мой дом, просто используйте этот ключ, чтобы открыть дверь.

对称加密

Симметричное шифрование в настоящее время является основнымAESа такжеDES,AESЭто стандарт нового поколения с высокой скоростью и более высоким уровнем безопасности.

AES

Существует пять режимов шифрования AES:CBC、ECB、CTR、OCF、CFB

  1. ECB: Метод электронной секретной книги требует только одного ключа, отличается простотой и удобен для параллельных вычислений.
  2. CBC: метод цепочки блоков зашифрованного текста требует вектора в дополнение к ключу.Функция вектора также используется для шифрования данных, поэтому безопасность этого лучше, чем у ECB.
  3. CTR, OCF, CFB: Реализация конкретных алгоритмов разная, плюсы и минусы тоже разные, и они такие же, как CBC, и все требуют ключей и векторов.

AES имеет три длины: 128 бит, 192 бит и 256 бит.Разница между этими тремя в основном заключается в длине ключа, 16-байтовый ключ = 128 бит, 24-байтовый ключ = 192 бит, 32-байтовый ключ = 256 бит. Следующая таблица:

длина длина ключа длина вектора
128 бит 16 16
192 бита 24 16
256 бит 32 16

DES

Шифрование по умолчаниюAESТо же, есть и пять режимов, кромеECBТребуется только ключ, для других режимов требуется и ключ, и вектор.

а такжеAESразница в том,DESДлина ключа всего 8 байт, и вектор тоже 8 байт.

Реализация кодирования

Реализация в nodejs

/**
 * @description 
 * 对称加密
 * @param {*} data 加密数据
 * @param {*} algorithm 加密算法
 * @param {*} key 密钥
 * @param {*} iv 向量
 * @returns
 */
function cipherivEncrypt(data, algorithm, key, iv) {
    const cipheriv = crypto.createCipheriv(algorithm, key, iv)
    let encrypted = cipheriv.update(data, 'utf8', 'hex');
    encrypted += cipheriv.final('hex');
    return encrypted
}

/**
 * @description
 * 对称解密
 * @param {*} data 解密数据
 * @param {*} algorithm 解密算法
 * @param {*} key 密钥
 * @param {*} iv 向量
 * @returns
 */
function cipherivDecrypt(data, algorithm, key, iv) {
    const decipher = crypto.createDecipheriv(algorithm, key, iv);
    let decrypted = decipher.update(data, 'hex', 'utf8');
    decrypted += decipher.final('utf8');
    return decrypted
}

использовать официальныйcryptoБиблиотека для реализации шифрования и дешифрования, вывод после шифрования в приведенном выше коде16Шестнадцатеричная строка, вы можете изменить данные на другие форматы в зависимости от конкретной ситуации.

Метод вызова следующий

// AES对称加解密
const str = 'xiaoliye';
const key = 'aaaaaaaaaaaaaaaaaaaaaaaa'; // 24
const iv = 'aaaaaaaaaaaaaaaaaaaaaaaa';  // 24
const cipherAesText = cipherivEncrypt(str, 'aes-192-cfb', key,iv)
const resultText = cipherivDecrypt(cipherAesText, 'aes-192-cfb', key,iv)
console.log(resultText === str) // true
// DES对称加解密
const str = 'xiaoliye';
const key = 'aaaaaaaa'; //8
const iv = 'aaaaaaaa';  //8
const cipherAesText = cipherivEncrypt(str, 'des-cfb', key,iv)
const resultText = cipherivDecrypt(cipherAesText, 'des-cfb', key,iv)
console.log(resultText === str) / true

Асимметричное шифрование

Асимметричное шифрование, есть два ключа, открытый ключ и закрытый ключ, как показано ниже:

非对称加密

Открытый ключ может быть обнародован, а закрытый ключ является закрытым и не может быть раскрыт. Вот как асимметричное шифрование получило свое название, потому что есть два ключа.

Отправитель шифрует данные с помощью открытого открытого ключа получателя.После получения данных получатель расшифровывает их с помощью закрытого ключа.После обработки бизнеса он шифрует данные, которые необходимо отправить обратно, с помощью закрытого ключа. Сторона, получающая данные, использует открытый ключ для расшифровки.

Этот процесс является асимметричным шифрованием и дешифрованием.Простое понимание состоит в том, что данные, зашифрованные с помощью открытого ключа, расшифровываются с помощью закрытого ключа, а данные, зашифрованные с помощью закрытого ключа, расшифровываются с помощью открытого ключа.

Асимметричное шифрование гораздо более безопасно, чем симметричное шифрование. При симметричном шифровании, если ключевой ключ случайно передается одной из сторон, секретный текст может быть взломан и изменен. В отличие от асимметричного шифрования, открытый ключ распространяется свободно, и пока сторона, выпустившая ключ, хорошо хранит закрытый ключ, безопасность является адекватной.

Реализация кодирования

Посмотрим на реализацию кодировки в узле или воспользуемся официальнойcryptoбиблиотека

  1. Данные, полученные функциями шифрования и дешифрования, имеют тип Buffer.Двоичный и буферный), поэтому нужно согласовать тип данных приема и вывода.
  2. параметрpaddingЭто метод заполнения, их так многоcrypto.constants.RSA_NO_PADDING, crypto.constants.RSA_PKCS1_PADDING, crypto.constants.RSA_PKCS1_OAEP_PADDING, т.к. глубоко не изучал, не буду расширять, но есть один момент, способ заполнения шифрования и дешифрования должен быть согласован.
const constants = require('constants')
const crypto = require('crypto')

/**
 * @description
 * 公钥加密数据
 * @param {*} data 待加密数据
 * @param {*} publicKey 公钥
 * @param {*} inputEncoding 加密数据类型
 * @param {*} outputEncoding 输出的数据类型
 * @param {*} padding 填充方式
 * @returns
 */
function publicEncrypt(data, publicKey, inputEncoding, outputEncoding, padding) {
    const encryptText = crypto.publicEncrypt({
        key: publicKey,
        padding: padding || constants.RSA_PKCS1_PADDING
    }, Buffer.from(data, inputEncoding));

    return encryptText.toString(outputEncoding);
}

/**
 * @description
 * 公钥解密数据
 * @param {*} data 待解密数据
 * @param {*} publicKey 公钥
 * @param {*} inputEncoding 解密数据类型
 * @param {*} outputEncoding 输出的数据类型
 * @param {*} padding 填充方式
 * @returns
 */
function publicDecrypt(data, publicKey, inputEncoding, outputEncoding, padding) {
    let decryptText = '';
    const decryptText = crypto.publicDecrypt({
        key: publicKey,
        padding: padding || constants.RSA_PKCS1_PADDING
    }, Buffer.from(data, inputEncoding));

    return decryptText.toString(outputEncoding);
}

/**
 * @description
 * 私钥加密数据
 * @param {*} data 待加密数据
 * @param {*} privateKey 私钥
 * @param {*} inputEncoding 加密数据类型
 * @param {*} outputEncoding 输出的数据类型
 * @param {*} padding 填充方式
 * @returns
 */
function privateEncrypt(data, privateKey, inputEncoding, outputEncoding, padding) {
    const encryptText = crypto.privateEncrypt({
        key: privateKey,
        padding: padding || constants.RSA_PKCS1_PADDING
    }, Buffer.from(data, inputEncoding));

    return encryptText.toString(outputEncoding);
}

/**
 * @description
 * 私钥解密数据
 * @param {*} data 待解密数据
 * @param {*} privateKey 私钥
 * @param {*} inputEncoding 解密数据类型
 * @param {*} outputEncoding 输出的数据类型
 * @param {*} padding 填充方式
 * @returns
 */
function privateDecrypt(data, privateKey, inputEncoding, outputEncoding, padding) {
    const decryptText = crypto.privateDecrypt({
        key: privateKey,
        padding: padding || constants.RSA_PKCS1_PADDING
    }, Buffer.from(data, inputEncoding));
    return decryptText.toString(outputEncoding);
}

Есть четыре функции: шифрование и дешифрование открытого ключа и шифрование и дешифрование закрытого ключа. Давайте посмотрим, как его использовать. Примером является пара ключей, созданная мной. Вы можете заменить ее самостоятельно.

const rsaPublicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCncWDMXEToSxtGQCmWY2ywl5CQ
tb81PXYZch4v5M8MNUZPpcmf+VDXQbuWqqTqV/tY7rLviu/BAkFbX9NiFCapF5lP
siVwSGWJQwq0S/++RCwB6yFVEzOKL25jANRBVNwmSOzojveCStYPcEs5Q829ld68
9TzluDDqUS69dTHGkQIDAQAB
-----END PUBLIC KEY-----`

const rsaPrivateKey = `-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKdxYMxcROhLG0ZA
KZZjbLCXkJC1vzU9dhlyHi/kzww1Rk+lyZ/5UNdBu5aqpOpX+1jusu+K78ECQVtf
02IUJqkXmU+yJXBIZYlDCrRL/75ELAHrIVUTM4ovbmMA1EFU3CZI7OiO94JK1g9w
SzlDzb2V3rz1POW4MOpRLr11McaRAgMBAAECgYEAhNa8/cQh4sxbKgOTOr1MKFlG
Fpgpxroo7I0Nh9+Vp1DIpD2Z1PF9ghijEyf0R/pe7LIKgWIPTWdVpIFEeSYVeH43
FLr3zwR9oXzwG7RQTSN4d/Xcvg+24ZxCrvDfn7qDIlXh0jOS0wCvna1or7xgPcOu
XG8J3BNbBdUixM0lk0ECQQDR4SCelWn0BY21jsFobX+pGqKOsj+tuvU4Cz47Gmev
qvq2suYXwLemkP7EqRu8iNso/IzvrdsuJDG76dzwC4D5AkEAzDz2cDrKOVmqYw7s
luOQFHl1TzmY7Umpd9YbZ5iXn0eCjIn1/e1risRF5+IeSpB84OVltUzj4cVDCbFd
9S1wWQJAIeKcFp5+9cPzxi1fMpIDO3Uua6WBvHXj44GFMZuow+byBY9KsOkPfZgJ
Wg0Hil/6KlrkEkpaic+ULAetASCKWQJAdMh/Gdlj/LsaxJ2qBvWEU1DIFU8X9Mbk
ElPpQ6lrOXaIXZgdgt8ZWTW1y0vuijBoV6iUKcEXpOdI1+gFk8YxsQJBAJsGJClf
E1mE6CZgegM82428g4osZznVXBO/QtrQsA78S1xo8bo4qwVm0jQBcto65gwlfeeB
Xm7MiIvNVBqzTVs=
-----END PRIVATE KEY-----
`

const str = 'xiaoliye'
const cipherText = publicEncrypt(str, rsaPublicKey, 'utf8', 'hex') // 公钥加密
const decryptText = privateDecrypt(cipherText, rsaPrivateKey, 'hex', 'utf8') // 私钥解密
console.log(str === decryptText) // true

const cipherTextPrivate = privateEncrypt(str,rsaPrivateKey,'utf8', 'hex') // 私钥加密
const decryptTextPublic = publicDecrypt(cipherTextPrivate,rsaPublicKey, 'hex', 'utf8') // 公钥解密
console.log(str === decryptTextPublic) // true

метод генерации ключей

В Интернете есть много инструментов, которые могут генерировать парные открытые и закрытые ключи одним щелчком мыши Taobao и WeChat предоставляют соответствующие инструменты или используютOpenSSLтакже может быть сгенерировано.

Алгоритм дайджеста (HASH)

Ввод любой длины используется для генерации серии псевдослучайных чисел фиксированной длины в соответствии с алгоритмом.Этот алгоритм является алгоритмом дайджеста.Он имеет несколько характеристик.

  1. Ключ не требуется, а зашифрованные данные не могут быть расшифрованы и необратимы.
  2. Длина сгенерированного дайджеста фиксирована и не зависит от ввода.
  3. Для одних и тех же входных данных, использующих одну и ту же реализацию, сгенерированные сводки должны быть одинаковыми, для разных входов сгенерированные сводки совершенно разные, то есть коллизий не будет.

Основываясь на этих характеристиках, алгоритмы дайджеста часто используются для создания подписей для проверки целостности данных.

Существует также хранилище пользовательских паролей.В настоящее время основным способом хранения паролей является использование алгоритма дайджеста для генерации уникального идентификатора.В целях обеспечения безопасности после дайджеста обычно добавляется строка случайных чисел (соль). генерируется один раз.

Текущие основные реализации:MD5а такжеSHA-2,MD5Итоговое резюме32байт,sha256Итоговое резюме64байт.

Реализация кодирования

До сих пор пользуюсь официальнойcryptoбиблиотека

/**
 * @description
 * md5
 * @param {*} data
 * @returns
 */
function md5(data){
    const hash = crypto.createHash('md5');
    return hash.update(data).digest('hex');
}

/**
 * @description
 * sha256
 * @param {*} data
 * @returns
 */
function sha256(data){
    const hash = crypto.createHash('sha256');
    return hash.update(data).digest('hex');
}

console.log(md5('asdf')) // 912ec803b2ce49e4a541068d495ab570
console.log(sha256('asdf')) // f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b

резюме

Работа, связанная с шифрованием, обычно выполняется фоновой разработкой, но красавчик фронтенда немного знает о шифровании, что сделает его крутым~

Друзья, с какими еще методами шифрования вы сталкивались? Добро пожаловать в общение друг с другом~