nodeJS之crypto加密

来源:http://www.cnblogs.com/xiaohuochai/archive/2017/06/14/7009977.html
-Advertisement-
Play Games

[1]crypto [2]MD5 [3]Hmac [4]AES [5]Diffie-Hellman ...


前面的話

  加密模塊提供了 HTTP 或 HTTPS 連接過程中封裝安全憑證的方法。也提供了 OpenSSL 的哈希,hmac, 加密(cipher), 解密(decipher), 簽名(sign) 和 驗證(verify) 方法的封裝。本文將詳細介紹加密crypto

 

crypto

【crypto.setEngine(engine[, flags])】

  為某些/所有 OpenSSL 函數載入並設置引擎(根據參數 flags 來設置)。

  engine 可能是 id,或者是指向引擎共用庫的路徑。

  flags是可選參數,預設值是ENGINE_METHOD_ALL ,可以是以下一個或多個參數的組合(在constants里定義)

ENGINE_METHOD_RSA
ENGINE_METHOD_DSA
ENGINE_METHOD_DH
ENGINE_METHOD_RAND
ENGINE_METHOD_ECDH
ENGINE_METHOD_ECDSA
ENGINE_METHOD_CIPHERS
ENGINE_METHOD_DIGESTS
ENGINE_METHOD_STORE
ENGINE_METHOD_PKEY_METH
ENGINE_METHOD_PKEY_ASN1_METH
ENGINE_METHOD_ALL
ENGINE_METHOD_NONE

【crypto.getCiphers()】

  返回支持的加密演算法名數組

var crypto = require('crypto');
console.log(crypto.getCiphers());
//[ 'aes-128-cbc',  'aes-128-ccm',  'aes-128-cfb',  'aes-128-cfb1',  'aes-128-cfb8',  'aes-128-ctr',  'aes-128-ecb',  'aes-128-gcm',  'aes-128-ofb',  'aes-128-xts',  'aes-192-cbc',  'aes-192-ccm',  'aes-192-cfb',  'aes-192-cfb1',  'aes-192-cfb8',  'aes-192-ctr',  'aes-192-ecb',  'aes-192-gcm',  'aes-192-ofb',  'aes-256-cbc',  'aes-256-ccm',  'aes-256-cfb',  'aes-256-cfb1',  'aes-256-cfb8',  'aes-256-ctr',  'aes-256-ecb',  'aes-256-gcm',  'aes-256-ofb',  'aes-256-xts',  'aes128',  'aes192',  'aes256',  'bf',  'bf-cbc',  'bf-cfb',  'bf-ecb',  'bf-ofb',  'blowfish',  'camellia-128-cbc',  'camellia-128-cfb',  'camellia-128-cfb1',  'camellia-128-cfb8',  'camellia-128-ecb',  'camellia-128-ofb',  'camellia-192-cbc',  'camellia-192-cfb',  'camellia-192-cfb1',  'camellia-192-cfb8',  'camellia-192-ecb',  'camellia-192-ofb',  'camellia-256-cbc',  'camellia-256-cfb',  'camellia-256-cfb1',  'camellia-256-cfb8',  'camellia-256-ecb',  'camellia-256-ofb',  'camellia128',  'camellia192',  'camellia256',  'cast',  'cast-cbc',  'cast5-cbc',  'cast5-cfb',  'cast5-ecb',  'cast5-ofb',  'des',  'des-cbc',  'des-cfb',  'des-cfb1',  'des-cfb8',  'des-ecb',  'des-ede',  'des-ede-cbc',  'des-ede-cfb',  'des-ede-ofb',  'des-ede3',  'des-ede3-cbc',  'des-ede3-cfb',  'des-ede3-cfb1',  'des-ede3-cfb8',  'des-ede3-ofb',  'des-ofb',  'des3',  'desx',  'desx-cbc',  'id-aes128-CCM',  'id-aes128-GCM',  'id-aes128-wrap',  'id-aes192-CCM',  'id-aes192-GCM',  'id-aes192-wrap',  'id-aes256-CCM',  'id-aes256-GCM',  'id-aes256-wrap',  'id-smime-alg-CMS3DESwrap',  'idea',  'idea-cbc',  'idea-cfb',  'idea-ecb',  'idea-ofb',  ... 15 more items ]

【crypto.getCiphers()】

  返回支持的哈希演算法名數組。

var crypto = require('crypto');
console.log(crypto.getHashes());
//[ 'DSA',  'DSA-SHA',  'DSA-SHA1',  'DSA-SHA1-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' ]

【crypto.getCurves()】

  返回支持的橢圓曲線名數組。

var crypto = require('crypto');
console.log(crypto.getCurves());
//[ 'Oakley-EC2N-3',  'Oakley-EC2N-4',  'brainpoolP160r1',  'brainpoolP160t1',  'brainpoolP192r1',  'brainpoolP192t1',  'brainpoolP224r1',  'brainpoolP224t1',  'brainpoolP256r1',  'brainpoolP256t1',  'brainpoolP320r1',  'brainpoolP320t1',  'brainpoolP384r1',  'brainpoolP384t1',  'brainpoolP512r1',  'brainpoolP512t1',  'c2pnb163v1',  'c2pnb163v2',  'c2pnb163v3',  'c2pnb176v1',  'c2pnb208w1',  'c2pnb272w1',  'c2pnb304w1',  'c2pnb368w1',  'c2tnb191v1',  'c2tnb191v2',  'c2tnb191v3',  'c2tnb239v1',  'c2tnb239v2',  'c2tnb239v3',  'c2tnb359v1',  'c2tnb431r1',  'prime192v1',  'prime192v2',  'prime192v3',  'prime239v1',  'prime239v2',  'prime239v3',  'prime256v1',  'secp112r1',  'secp112r2',  'secp128r1',  'secp128r2',  'secp160k1',  'secp160r1',  'secp160r2',  'secp192k1',  'secp224k1',  'secp224r1',  'secp256k1',  'secp384r1',  'secp521r1',  'sect113r1',  'sect113r2',  'sect131r1',  'sect131r2',  'sect163k1',  'sect163r1',  'sect163r2',  'sect193r1',  'sect193r2',  'sect233k1',  'sect233r1',  'sect239k1',  'sect283k1',  'sect283r1',  'sect409k1',  'sect409r1',  'sect571k1',  'sect571r1',  'wap-wsg-idm-ecid-wtls1',  'wap-wsg-idm-ecid-wtls10',  'wap-wsg-idm-ecid-wtls11',  'wap-wsg-idm-ecid-wtls12',  'wap-wsg-idm-ecid-wtls3',  'wap-wsg-idm-ecid-wtls4',  'wap-wsg-idm-ecid-wtls5',  'wap-wsg-idm-ecid-wtls6',  'wap-wsg-idm-ecid-wtls7',  'wap-wsg-idm-ecid-wtls8',  'wap-wsg-idm-ecid-wtls9' ]

 

MD5

  MD5是一種常用的哈希演算法,用於給任意數據一個“簽名”。這個簽名通常用一個十六進位的字元串表示:

【crypto.createHash(algorithm)】

  創建並返回一個哈希對象,使用指定的演算法來生成哈希摘要。

  參數 algorithm 取決於平臺上 OpenSSL 版本所支持的演算法。例如,'sha1', 'md5', 'sha256', 'sha512' 等等

【hash.update(data[, input_encoding])】

  根據 data 來更新哈希內容,編碼方式根據 input_encoding 來定,有 'utf8', 'ascii' 或 'binary'。如果沒有傳入值,預設編碼方式是'utf8'。如果 data 是 Buffer, input_encoding 將會被忽略。

  因為它是流式數據,所以可以使用不同的數據調用很多次。

【hash.digest([encoding])】

  計算傳入的數據的哈希摘要。encoding 可以是 'hex', 'binary' 或 'base64',如果沒有指定encoding ,將返回 buffer。

  [註意]調用 digest() 後不能再用 hash 對象。

var crypto = require('crypto');
var hash = crypto.createHash('md5');

// 可任意多次調用update():
hash.update('Hello, world!');
hash.update('Hello, nodejs!');

console.log(hash.digest('hex')); // 7e1977739c748beac0c0fd14fd26a544

 

Hmac

  Hmac演算法也是一種哈希演算法,它可以利用MD5或SHA1等哈希演算法。不同的是,Hmac還需要一個密鑰:

【crypto.createHmac(algorithm, key)】

  創建並返回一個 hmac 對象,用指定的演算法和秘鑰生成 hmac 圖譜。

  它是可讀寫的流 stream 。寫入的數據來用計算 hmac。當寫入流結束後,使用 read() 方法來獲取計算後的值。也支持老的 update 和 digest 方法。

  參數 algorithm 取決於平臺上 OpenSSL 版本所支持的演算法,參見前面的 createHash。key是 hmac 演算法中用的 key

【hmac.update(data)】

  根據 data 更新 hmac 對象。因為它是流式數據,所以可以使用新數據調用多次。

【hmac.digest([encoding])】

  計算傳入數據的 hmac 值。encoding可以是 'hex', 'binary' 或 'base64',如果沒有指定encoding ,將返回 buffer。

  [註意]調用 digest() 後不能再用 hmac 對象

var crypto = require('crypto');
var hmac = crypto.createHmac('sha256', 'match');

hmac.update('Hello, world!');
hmac.update('Hello, nodejs!');
//e82a58066cae2fae4f44e58be1d589b66a5d102c2e8846d796607f02a88c1649
console.log(hmac.digest('hex')); 

 

AES

  AES是一種常用的對稱加密演算法,加解密都用同一個密鑰。crypto模塊提供了AES支持,但是需要自己封裝好函數,便於使用:

【crypto.createCipher(algorithm, password)】

  使用傳入的演算法和秘鑰來生成並返回加密對象。

  algorithm 取決於 OpenSSL,例如'aes192'等。password 用來派生 key 和 IV,它必須是一個'binary' 編碼的字元串或者一個buffer。

  它是可讀寫的流 stream 。寫入的數據來用計算 hmac。當寫入流結束後,使用 read() 方法來獲取計算後的值。也支持老的update 和 digest 方法。

【cipher.update(data[, input_encoding][, output_encoding])】

  根據 data 來更新哈希內容,編碼方式根據 input_encoding 來定,有 'utf8', 'ascii' or 'binary'。如果沒有傳入值,預設編碼方式是'binary'。如果data 是 Buffer,input_encoding 將會被忽略。

  output_encoding 指定了輸出的加密數據的編碼格式,它可用是 'binary', 'base64' 或 'hex'。如果沒有提供編碼,將返回 buffer 。

  返回加密後的內容,因為它是流式數據,所以可以使用不同的數據調用很多次。

【cipher.final([output_encoding])】

  返回加密後的內容,編碼方式是由 output_encoding 指定,可以是 'binary', 'base64' 或 'hex'。如果沒有傳入值,將返回 buffer。

  [註意]cipher 對象不能在 final() 方法之後調用。

var crypto = require('crypto');
function aesEncrypt(data, key) {
    const cipher = crypto.createCipher('aes192', key);
    var crypted = cipher.update(data, 'utf8', 'hex');
    crypted += cipher.final('hex');
    return crypted;
}
var data = 'Hello, this is a secret message!';
var key = 'Password!';
var encrypted = aesEncrypt(data, key);
//8a944d97bdabc157a5b7a40cb180e713f901d2eb454220d6aaa1984831e17231f87799ef334e3825123658c80e0e5d0c
console.log(encrypted);

【crypto.createDecipher(algorithm, password)】

  根據傳入的演算法和密鑰,創建並返回一個解密對象。這是 createCipher() 的鏡像

【decipher.update(data[, input_encoding][, output_encoding])】

  使用參數 data 更新需要解密的內容,其編碼方式是 'binary','base64' 或 'hex'。如果沒有指定編碼方式,則把 data 當成 buffer 對象。

  如果 data 是 Buffer,則忽略 input_encoding 參數。

  參數 output_decoding 指定返迴文本的格式,是 'binary', 'ascii' 或 'utf8' 之一。如果沒有提供編碼格式,則返回 buffer。

【decipher.final([output_encoding])】

  返回剩餘的解密過的內容,參數 output_encoding 是 'binary', 'ascii' 或 'utf8',如果沒有指定編碼方式,返回 buffer。

  [註意]decipher對象不能在 final() 方法之後使用。

var crypto = require('crypto');
function aesDecrypt(encrypted, key) {
    const decipher = crypto.createDecipher('aes192', key);
    var decrypted = decipher.update(encrypted, 'hex', 'utf8');
    decrypted += decipher.final('utf8');
    return decrypted;
}
var data = 'Hello, this is a secret message!';
var key = 'Password!';
var encrypted = '8a944d97bdabc157a5b7a40cb180e713f901d2eb454220d6aaa1984831e17231f87799ef334e3825123658c80e0e5d0c';
var decrypted = aesDecrypt(encrypted, key);
console.log(decrypted);//Hello, this is a secret message!

  可以看出,加密後的字元串通過解密又得到了原始內容。

  註意到AES有很多不同的演算法,如aes192aes-128-ecbaes-256-cbc等,AES除了密鑰外還可以指定IV(Initial Vector),不同的系統只要IV不同,用相同的密鑰加密相同的數據得到的加密結果也是不同的。加密結果通常有兩種表示方法:hex和base64,這些功能Nodejs全部都支持,但是在應用中要註意,如果加解密雙方一方用Nodejs,另一方用Java、PHP等其它語言,需要仔細測試。如果無法正確解密,要確認雙方是否遵循同樣的AES演算法,字元串密鑰和IV是否相同,加密後的數據是否統一為hex或base64格式

【crypto.createCipheriv(algorithm, key, iv)】

  創建並返回一個加密對象,用指定的演算法,key 和 iv。

  algorithm 參數和 createCipher() 一致。key 在演算法中用到.iv 是一個initialization vector.

  key 和 iv 必須是 'binary' 的編碼字元串或buffers.

【crypto.createDecipheriv(algorithm, key, iv)】

  根據傳入的演算法,密鑰和 iv,創建並返回一個解密對象。這是 createCipheriv() 的鏡像。

const crypto = require('crypto');

function aesEncryptiv(data, key,iv) {
    const cipher = crypto.createCipher('aes192', key, iv);
    var crypted = cipher.update(data, 'utf8', 'hex');
    crypted += cipher.final('hex');
    return crypted;
}

function aesDecryptiv(encrypted, key,iv) {
    const decipher = crypto.createDecipher('aes192', key, iv);
    var decrypted = decipher.update(encrypted, 'hex', 'utf8');
    decrypted += decipher.final('utf8');
    return decrypted;
}

var data = 'Hello, this is a secret message!';
var key = 'Password!';
var iv = 'match';
var encrypted = aesEncryptiv(data, key, iv);
var decrypted = aesDecryptiv(encrypted, key, iv);
//Hello, this is a secret message!
console.log(data);
//8a944d97bdabc157a5b7a40cb180e713f901d2eb454220d6aaa1984831e17231f87799ef334e3825123658c80e0e5d0c
console.log(encrypted);
//Hello, this is a secret message!
console.log(decrypted);

 

Diffie-Hellman

【crypto.createDiffieHellman(prime[, prime_encoding][, generator][, generator_encoding])】

  使用傳入的 prime 和 generator 創建 Diffie-Hellman 秘鑰交互對象。

  generator 可以是數字,字元串或Buffer。如果沒有指定 generator,使用 2

  prime_encoding 和 generator_encoding 可以是 'binary', 'hex', 或 'base64'。

  如果沒有指定 prime_encoding, 則 Buffer 為 prime。如果沒有指定 generator_encoding ,則 Buffer 為 generator。

【diffieHellman.generateKeys([encoding])】

  生成秘鑰和公鑰,並返回指定格式的公鑰。這個值必須傳給其他部分。編碼方式: 'binary', 'hex', 或 'base64'。如果沒有指定編碼方式,將返回 buffer。

【diffieHellman.getPrime([encoding])】

  用參數 encoding 指明的編碼方式返回 Diffie-Hellman 質數,編碼方式為: 'binary', 'hex', 或 'base64'。 如果沒有指定編碼方式,將返回 buffer。

【diffieHellman.getGenerator([encoding])】

  用參數 encoding 指明的編碼方式返回 Diffie-Hellman 生成器,編碼方式為: 'binary', 'hex', 或 'base64'. 如果沒有指定編碼方式 ,將返回 buffer。

【diffieHellman.computeSecret(other_public_key[, input_encoding][, output_encoding])】

  使用 other_public_key 作為第三方公鑰來計算並返回共用秘密(shared secret)。秘鑰用input_encoding 編碼。編碼方式為:'binary', 'hex', 或 'base64'。如果沒有指定編碼方式 ,預設為 buffer。

  如果沒有指定返回編碼方式,將返回 buffer。

DH演算法

  DH演算法是一種密鑰交換協議,它可以讓雙方在不泄漏密鑰的情況下協商出一個密鑰來。DH演算法基於數學原理,比如小明和小紅想要協商一個密鑰,可以這麼做:

  1、小明先選一個素數和一個底數,例如,素數p=23,底數g=5(底數可以任選),再選擇一個秘密整數a=6,計算A=g^a mod p=8,然後大聲告訴小紅:p=23,g=5,A=8;

  2、小紅收到小明發來的p,g,A後,也選一個秘密整數b=15,然後計算B=g^b mod p=19,並大聲告訴小明:B=19;

  3、小明自己計算出s=B^a mod p=2,小紅也自己計算出s=A^b mod p=2,因此,最終協商的密鑰s為2。

  在這個過程中,密鑰2並不是小明告訴小紅的,也不是小紅告訴小明的,而是雙方協商計算出來的。第三方只能知道p=23,g=5,A=8,B=19,由於不知道雙方選的秘密整數a=6和b=15,因此無法計算出密鑰2。

  用crypto模塊實現DH演算法如下:

var crypto = require('crypto');

// xiaoming's keys:
var ming = crypto.createDiffieHellman(512);
var ming_keys = ming.generateKeys();

var prime = ming.getPrime();
var generator = ming.getGenerator();

//Prime: 8df777257625c66821af697652f28e93af05b9f779af919111b89816faa11c36fcf9df04c76811471a6099800213c4fe8e3fbec8d2f90bd00795e4b7fd241603
console.log('Prime: ' + prime.toString('hex'));
//Generator: 02
console.log('Generator: ' + generator.toString('hex'));

// xiaohong's keys:
var hong = crypto.createDiffieHellman(prime, generator);
var hong_keys = hong.generateKeys();

// exchange and generate secret:
var ming_secret = ming.computeSecret(hong_keys);
var hong_secret = hong.computeSecret(ming_keys);

//Secret of Xiao Ming: 4237157ab4c9211f78ffdb67d127d749cec91780d594b81a7e75f1fb591fecb84f33ae6591e1edda4bc9685b503010fe8f9928c6ed69e4ff9fdb44adb9ba1539
console.log('Secret of Xiao Ming: ' + ming_secret.toString('hex'));
//Secret of Xiao Hong: 4237157ab4c9211f78ffdb67d127d749cec91780d594b81a7e75f1fb591fecb84f33ae6591e1edda4bc9685b503010fe8f9928c6ed69e4ff9fdb44adb9ba1539
console.log('Secret of Xiao Hong: ' + hong_secret.toString('hex'))

   [註意]每次輸出都不一樣,因為素數的選擇是隨機的。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 世界,您好! ...
  • 最近花了差不多1天的時間在折騰一個Bug,該Bug的表象如下: 這個Bug還特別獨特,在開發電腦中無提示,在終端用戶那裡每次使用軟體的時候都報這個。仔細思考了一下最近在源碼中新添加的功能,沒發現有啥特別明顯的問題。於是,根據字面意思的理解是“運行時錯誤”,所以一開始解決這個問題的思路是將所有應用程式 ...
  • 前面寫了一篇shell多進程的文章,多進程實現起來非常簡單,但是當有大量任務,如有一百個很大的日誌文件需要分析 此時若同時並行100個進程,那io肯定要爆,所以必須要控制併發數 linux 有兩種管道:匿名管道和命名管道 匿名管道即常用的'|',命名管道可以使用mkfifo命令創建 管道有一個特性: ...
  • ExtJs2.0好像不支持單選框組,因此用兩個name相同單選框來實現單選框組 var radio1 = new Ext.form.Radio({boxLabel:'男',name:'sex',id:'yes',inputValue:'0',width : 150, height : 20}); v ...
  • Java就是用來做項目的!Java的主要應用領域就是企業級的項目開發!要想從事企業級的項目開發,你必須掌握如下要點: 1、掌握項目開發的基本步驟 2、具備極強的面向對象的分析與設計技巧 3、掌握用例驅動、以架構為核心的主流開發方法 沒有人願意自己一輩子就滿足於掌握了一些代碼實現的技巧,別人告訴你要實 ...
  • 設計此種編碼是為了使二進位數據可以通過非純 8-bit 的傳輸層傳輸,例如電子郵件的內容就是通過base64轉碼後傳輸的。Base64-encoded後, 數據要比原始數據多占用 33% 左右的空間。 利用base64加密文件: 解密base64加密後的文件: 其實上面的操作還算不上加密,只要懂解碼 ...
  • 從現在開始,分享我讀過的技術文章。 ...
  • 一、擴展的功能 1、初始化時,會自動創建一個select標簽; 2、當改變select值時,日期也會自動改變,並且會調用apply按鈕的click事件 3、點擊此處進行預覽 4、github地址:https://github.com/lanleiming/daterangepicker-extend ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...