NodeJS暗号化——cryptモジュール


原文を読む
暗号化プロファイル
暗号化は、暗号化された情報を取得しても、暗号化された情報が得られなくても、情報の本当の意味が分かりません.このようにして、ネットワークデータ伝送の安全性を高めます.暗号化アルゴリズムによくあるのは、ハシーアルゴリズム、HMACアルゴリズム、署名、対称性暗号化アルゴリズム、非対称性暗号化アルゴリズムです.暗号化アルゴリズムも可逆と不可逆に分けられています.例えばmd5は非可逆暗号であり、暴力解読(衝突)しかできません.NodeJS開発においては、これらの暗号化アルゴリズムを直接使用しています.cryptoのハッシュ、HMAC、暗号解読、署名、検証機能を含む暗号化機能を提供しています.使用時にはインストール不要です.
ハッシュ・アルゴリズム
ハッシュアルゴリズムは、任意の長さの入力を固定長の出力に変換するためのハッシュアルゴリズムとも呼ばれ、一般的にはOpenSSLmd5などがあり、これらのアルゴリズムは、元のデータに対する変換プロセスが暗号化と呼ばれることができるかどうかで論争されています.後で説明するために、まず暗号化と呼ばれます.
//            
const crypto = require("crypto");

// getHashes              
console.log(crypto.getHashes());

// [ 'DSA', 'DSA-SHA', 'DSA-SHA1', 'DSA-cSHA1-old',
//   'RSA-MD4', 'RSA-MD5', 'RSA-MDC2', 'RSA-RIPEMD160',
//   'RSA-SHA', 'RSA-SHA1', 'RSA-SHA1-2', 'RSA-SHA224',
//   'RSA-SHA256', 'RSA-SHA384', 'RSA-SHA512',
//   'dsaEncryption', 'dsaWithSHA', 'dsaWithSHA1', 'dss1',
//   'ecdsa-with-SHA1', 'md4', 'md4WithRSAEncryption',
//   'md5', 'md5WithRSAEncryption', 'mdc2', 'mdc2WithRSA',
//   'ripemd', 'ripemd160', 'ripemd160WithRSA', 'rmd160',
//   'sha', 'sha1', 'sha1WithRSAEncryption', 'sha224',
//   'sha224WithRSAEncryption', 'sha256',
//   'sha256WithRSAEncryption', 'sha384',
//   'sha384WithRSAEncryption', 'sha512',
//   'sha512WithRSAEncryption', 'shaWithRSAEncryption',
//   'ssl2-md5', 'ssl3-md5', 'ssl3-sha1', 'whirlpool' ]
sha1は開発においてよく使用されるアルゴリズムの一つであり、公式には要約アルゴリズムと呼ばれ、以下のいくつかの特徴がある.
  • 不可逆;
  • は、暗号化されたコンテンツの長さにかかわらず、最後に出力された結果の長さは等しくなる.
  • コンテンツの異なる出力の結果は全く異なり、コンテンツの同じ出力の結果は全く同じである.
  • 同じ入力がmd5によって暗号化されて戻ってきた結果は全く同じであるため、解読時には「衝突」によって暴力的に解読され、md5によって暗号化されたmd5によって連続して暗号化されたときには解読されにくいので、3を使用して通常何度も暗号化される.
    // md5    ——    Buffer
    const crytpo = require("crytpo");
    
    let md5 = crytpo.createHash("md5"); //    md5
    let md5Sum = md5.update("hello"); // update   
    let result = md5Sum.digest(); //        
    
    console.log(result); // 
    md5メソッドパラメータは、暗号化された戻り値のフォーマットを指定するために使用され、デフォルトでは暗号化されたBufferに返されない.一般的なパラメータはdigesthexBase64は16進数を表し、暗号化された長さはhex32の結果長さはBase6424で終了する.
    // md5    ——       
    const crypto = require("crypto");
    
    let md5 = crypto.createHash("md5");
    let md5Sum = md5.update("hello");
    let result = md5Sum.digest("hex");
    
    console.log(result); // 5d41402abc4b2a76b9719d911017c592
    // md5    ——    Base64
    const crypto = require("crypto");
    
    let md5 = crypto.createHash("md5");
    let md5Sum = md5.update("hello");
    let result = md5Sum.digest("Base64");
    
    console.log(result); // XUFAKrxLKna5cZ2REBfFkg==
    ==方法の戻り値はupdateであり、現在の例であるので、チェーンコールをサポートし、長い情報を何回もthis方法を呼び出してセグメント暗号化しても良いし、update方法を呼び出しても同様に全体の暗号化された値に戻ります.
    //          
    const crypto = require("crypto");
    
    let result = crypto
        .createHash("md5")
        .update("he")
        .update("llo")
        .digest("hex");
    
    console.log(result); // 5d41402abc4b2a76b9719d911017c592
    digestを使用してセグメント化暗号化ができるので、ストリームと関連して使用することができ、実はupdateの本質はcryptoタイプの変換ストリームを作成することであり、読み取り可能なストリームを書き込み可能なストリームに変換することができる.
    //             md5   
    const crypto = require("crypto");
    let fs = require("fs");
    
    let md5 = crypto.createHash("md5");
    let rs = fs.createReadSteam("./readme.txt", {
        highWaterMark: 3
    });
    
    //        
    rs.on("data", data => md5.update(data));
    
    rs.on("end", () => {
        let result = md5.digest("hex");
        console.log(result);
    });
    使用シーン1:サーバとサーバの間で通信送信を行うなど、データのチェックによく使われます.ダイジェストにTransformを加えて要約を暗号化した後の暗文は、受信側がデータを取得した後に、同じmd5アルゴリズムで暗号化して暗号化された後、暗文ダイジェストと比較して検証されます.データ伝送中にハイジャックされたり、改竄されたりするのを防ぐためです.使用シーン2:ブラウザキャッシュポリシーでは、静的リソースに関する情報のダイジェストをmd5を用いて暗号化し、暗号化された鍵をサーバに送信するたびに照合すればよく、ファイルの内容全体を比較することはない.
    短所:md5のハッシュアルゴリズムを使用して暗号化することが規定されているので、他の人は同じアルゴリズムを使って情報を偽造することができ、安全性は高くない.
    Hmacアルゴリズム
    1、Hmacアルゴリズムの使用
    Hmacアルゴリズムはまた塩添加アルゴリズムとも呼ばれ、署名の完全性の破壊を阻止するためにハッシュアルゴリズムを一つの鍵と結合し、md5暗号化のいくつかの特徴を備えている.
    //         
    const crytpo = require("crytpo");
    
    let hmac = crytpo.createHmac("sha1", "panda");
    let result = hmac.update("hello").digest("Base64");
    
    console.log(result); // 7spMLxN8WJdcEtQ8Hm/LR9pUE3YsIGag9Dcai7lwioo=
    md5の最初のパラメータは、同じcrytpo.createHmacであり、暗号化のアルゴリズムであり、一般的にはcrytpo.createHashおよびsha1を使用しており、第2のパラメータは鍵である.sha256方法で生成された暗号化結果の長さはdigestより大きく、md5で生成された結果の長さはhex64で生成された結果の長さはBase64であり、44で終了する.
    セキュリティは=より高く、鍵によって暗号化されていますが、鍵が解読できないことが分かりません.欠点は鍵伝送のプロセスがハイジャックされやすく、いくつかのランダム鍵を生成することによって回避できます.
    2、鍵の作成方法md5クライアントをインストールし、コマンドラインを介して保存鍵のファイルを生成することができます.
    openssl genrsa-out rsa_prvate.key 1024openSSHは生成鍵を表し、openssl genrsaは出力ファイルを表し、-outはファイル名を表し、rsa_private.keyは出力鍵のサイズを表している.
    //                 
    const fs = require("fs");
    const crytpo = require("crytpo");
    const path = require("path");
    
    let key = fs.readFileSync(path.join(__dirname, "/rsa_private.key"));
    let hmac = crytpo.createHmac("sha256", key);
    
    let result = hmac.update("hello").digest("Base64");
    
    console.log(result); // bmi2N+6kwgwt5b+U+zSgjL/NFs+GsUnZmcieqLKBy4M=
    対称性の暗号化
    対称性暗号化は、データを送信する際に、鍵と暗号化アルゴリズムを用いて暗号化され、データを受信する際には同じ鍵と暗号化アルゴリズムの逆アルゴリズム(復号アルゴリズム)を用いて復号される必要があり、すなわち対称性暗号化のプロセスは可逆的であり、1024で使用されるアルゴリズムはcrytpoである.
    //      
    const fs = require("fs");
    const crypto = require("crypto");
    const path = require("path");
    
    let key = fs.readFileSync(path.join(__dirname, "/rsa_private.key"));
    
    //   
    let cipher = crypto.createCipher("blowfish", key);
    cipher.update("hello");
    
    // final         
    let result = cipher.final("hex");
    console.log(result); // 3eb9943113c7aa1e
    
    //   
    let decipher = crypto.createDecipher("blowfish", key);
    decipher.update(result, "hex");
    
    let data = decipher.final("utf8");
    console.log(data); // hello
    暗号化はblowfish方法を使用して、暗号解読はcrypto.createCipher方法を使用するが、使用するアルゴリズムと鍵は同じでなければならない.crypto.createDecipherのように、暗号化時のフォーマットを第2のパラメータで指定しなければならない.
    対称性の暗号化を使用する文字列は長さ制限があり、update文字を超えてはいけません.そうでないと暗号化に成功しますが、復号できません.
    短所:鍵は伝送中に入手しやすく、安全リスクがある.
    非対称暗号化
    非対称暗号化相も可逆的であり、対称性よりも安全であり、メッセージ送信者と受信者はローカルで鍵のペアを作成し、公開鍵と秘密鍵を互いに相手に送信し、メッセージ送信時には相手の公開鍵を使って暗号化し、相手がメッセージを受信した後に彼の秘密鍵を使って解読する.このように、公開鍵の配信中に切断されても解読できない.公開鍵の暗号化されたメッセージは、ペアの秘密鍵のみが復号されるからである.
    次に、hexを使用して、以前に生成された秘密鍵finalに対して、対応する公開鍵を生成し、以下のように命令する.
    openssl rsa-in rsa_prvate.key-pubout-out rsa_public.key
    上記のコマンドは、1つの秘密鍵から対応する公開鍵を生成し、utf8は公開鍵出力を表し、7は公開鍵のファイル名である.
    //       
    const fs = require("fs");
    const crypto = require("crypto");
    const path = require("path");
    
    //        
    let publicKey = fs.readFileSync(path.join(__dirname, "/rsa_public.key"));
    let privateKey = fs.readFileSync(path.join(__dirname, "/rsa_private.key"));
    
    //   
    let secret = crytpo.publicEncrypt(publicKey, Buffer.from("hello"));
    
    //   
    let result = crytpo.provateDecrypt(privateKey, secret);
    
    console.log(result); // hello
    公開鍵を用いて暗号化する方法はopenSSHであり、第一のパラメータは公開鍵であり、第二のパラメータは暗号化情報であり、秘密鍵を用いて復号する方法はrsa_private.keyであり、第一のパラメータは秘密鍵であり、第二のパラメータは復号情報である.
    署名する
    署名は非対称性暗号と非常に類似しており、公開鍵と秘密鍵とは異なり、相手は公開鍵を用いて暗号解読検証を行い、このデータが秘密鍵の所有者から送信された元のデータであることを保証し、ネットワーク内の伝送過程では変更されていない.
    また、以下のように署名コードを実装するために-pubout -outおよびrsa_public.keyを公開鍵および秘密鍵としても使用する.
    //   
    const fs = require("fs");
    const crypto = require("crypto");
    const path = require("path");
    
    //        
    let publicKey = fs.readFileSync(path.join(__dirname, "rsa_public.key"), "ascii");
    let privateKey = fs.readFileSync(path.join(__dirname, "rsa_private.key"), "ascii");
    
    //     
    let sign = crypto.createSign("RSA-SHA256");
    sign.update("panda");
    let signed = sign.sign(privateKey, "hex");
    
    //     
    let verify = crypto.createVerify("RSA-SHA256");
    verify.update("panda");
    let verifyResult = verify.verify(publicKey, signed, "hex");
    
    console.log(verifyResult); // true
    署名を生成するcrytpo.publicEncrypt方法には2つのパラメータがあり、第1のパラメータは秘密鍵であり、第2のパラメータは署名を生成するフォーマットであり、最後に返したcrytpo.provateDecryptは生成した署名(文字列)である.
    署名を検証するrsa_public.key方法には、3つのパラメータがあり、1つ目のパラメータは公開鍵であり、2番目のパラメータは検証された署名であり、3番目のパラメータは署名を生成するときのフォーマットであり、ブール値に戻ります.すなわち、検証されたかどうかです.
    使用シーン:cookie署名をブラウザに返すためによく使われています.ブラウザがドメインサーバにアクセスしてクッキーを持ってきたら検証します.クッキーが改竄されるのを防ぎ、CSRFスパンが偽造を要求します.
    締め括りをつける
    様々な項目は、データ伝送時に情報の感度と用途に応じて異なる暗号化アルゴリズムと暗号化方式を行い、NodeJSにおいてrsa_private.keyのAPIは、完全に私たちの暗号化ニーズを実現することができ、上の暗号化スキームを組み合わせて使用して、より複雑な暗号化スキームを実現することもできる.