Skip to content
Open
250 changes: 235 additions & 15 deletions nodejs-V5110-Doc/Crypto/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,27 +80,247 @@
- [Recent ECDH Changes](#recent-ecdh-changes)
- [Support for weak or compromised algorithms](#support-for-weak-or-compromised-algorithms)


# Crypto
# Determining if crypto support is unavailable
# Class: Certificate
`Crytpo`模組提供了包含OpenSSL's hash、HMAC、cipher、decipher、sign和verify等的加密的功能
用`require('crypto')`來載入這個模組
```javascript
const crypto = require('crypto');

const secret = 'abcdefg';
const hash = crypto.createHmac('sha256', secret)
.update('I love cupcakes')
.digest('hex');
console.log(hash);
// Prints:
// c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good


## Determining if crypto support is unavailable
如果沒有載入`crypto`的模組支援的話Node.js是可以建立的,但在有些時候使用`require('crypto')`則會得到錯誤訊息
```javascript
var crypto;
try {
crypto = require('crypto');
} catch (err) {
console.log('crypto support is disabled!');
}
```

## Class: Certificate
SPKAC最初是由Netscape實現了一個證書簽名請求機制,目前正式指定為[HTML5的keygen元素](http://www.w3.org/TR/html5/forms.html#the-keygen-element)的一部分

`crypto`模組提供了`Certificate`類別和SPKAC數據的工作,最常見的用法是生成HTML5元素`<keygen>`的輸出處理
Node.js使用[OpenSSL的SPKAC](https://www.openssl.org/docs/apps/spkac.html)執行

### new crypto.Certificate()
要實例`Certificate`類別可以用關鍵字`new`或是直接呼叫`crypto.Certificate()`來當成一個函數
```javascript
const crypto = require('crypto');

const cert1 = new crypto.Certificate();
const cert2 = crypto.Certificate();
```

### certificate.exportChallenge(spkac)
`SPKAC`的資料結構包含了一個公開的key和challenge
`certificate.exportChallenge()`可以以一個Node.js Buffer的形式return chanllenge的部件
SPKAC參數可以是一個字串或Buffer
```javascript
const cert = require('crypto').Certificate();
const spkac = getSpkacSomehow();
const challenge = cert.exportChallenge(spkac);
console.log(challenge.toString('utf8'));
// Prints the challenge as a UTF8 string
```

### certificate.exportPublicKey(spkac)
`SPKAC`的資料結構包含了一個公開的key和chanllenge
`certificate.exportPublicKey()`可以以一個Node.js Buffer的形式return 公開的key
`SPKAC`參數可以是一個字串或Buffer
```javascript
const cert = require('crypto').Certificate();
const spkac = getSpkacSomehow();
const publicKey = cert.exportPublicKey(spkac);
console.log(publicKey);
// Prints the public key as <Buffer ...>
```

### certificate.verifySpkac(spkac)
# Class: Cipher
如果`SPKAC`的資料結構式有效的會return `true`否則會return `false`
`SPKAC`參數必須是一個Node.js的Buffer
```javascript
const cert = require('crypto').Certificate();
const spkac = getSpkacSomehow();
console.log(cert.verifySpkac(new Buffer(spkac)));
// Prints true or false
```

## Class: Cipher
`Cipher`類別常用於對資料進行加密,這個類別主要有兩個使用方式:
- 包裝成一個可以讀寫的stream,能寫入未加密資料或讀出加密資料
- 用cipher.update()或cipher.final()方法產生加密資料
crypto.createCipher() 或 crypto.createCipheriv()方法常用於創`Cipher`的實例,`Cipher`的物件不能使用`new`來創建

例:將`Cipher`物件封裝成stream:
```javascript
const crypto = require('crypto');
const cipher = crypto.createCipher('aes192', 'a password');

var encrypted = '';
cipher.on('readable', () => {
var data = cipher.read();
if (data)
encrypted += data.toString('hex');
});
cipher.on('end', () => {
console.log(encrypted);
// Prints: ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504
});

cipher.write('some clear text data');
cipher.end();
```

例:使用`Cipher`和piped stream:
```javascript
const crypto = require('crypto');
const fs = require('fs');
const cipher = crypto.createCipher('aes192', 'a password');

const input = fs.createReadStream('test.js');
const output = fs.createWriteStream('test.enc');

input.pipe(cipher).pipe(output);
```

例:使用cipher.update() 和 cipher.final() 方法:
```javascript
const crypto = require('crypto');
const cipher = crypto.createCipher('aes192', 'a password');

var encrypted = cipher.update('some clear text data', 'utf8', 'hex');
encrypted += cipher.final('hex');
console.log(encrypted);
// Prints: ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504
```

### cipher.final([output_encoding])
return剩餘的解密內容
如果`output_encoding`參數是`'binary'`、`'base64'`或`'hex'`中的一種,則返回一個字串
如果沒有提供`output_encoding`,則返回一個Buffer

一旦使用了`cipher.final()`方法後,`Cipher`物件就不能再用於加密
如果多次使用`cipher.final()`將會丟回錯誤

### cipher.setAAD(buffer)
當使用加密認證模式(目前只支援`GCM`)時,`cipher.setAAD()`方法用於輸入額外認證資料(AAD)參數的值

### cipher.getAuthTag()
當使用加密認證模式(目前只支援`GCM`)時,`cipher.getAuthTag()`方法會return一個包含認證標籤的buffer

`cipher.getAuthTag()`方法只能在cipher.final()方法後使用

### cipher.setAutoPadding(auto_padding=true)
當使用區塊加密演算法時,`Cipher`類別會自動填充輸入的資料到適當的區塊大小,如果要禁用預設填充可以用`cipher.setAutoPadding(false)`

當`auto_padding`的值是`false`時,輸入的資料長度必須是cipher區塊大小的倍數,否則cipher.final()會丟回錯誤
禁用自動填充是個有用的非標準填充,例如用0x0替代PKCS填充

`cipher.setAutoPadding()`方法必須在cipher.final()之後使用

### cipher.update(data[, input_encoding][, output_encoding])
# Class: Decipher
用在更新資料`(data)`的cipher,如果有`input_encoding`的參數,那必須是`'utf8'`、`'ascii'`或`'binary'`
資料`(data)`參數須是一個指定編碼格式的字串,如果沒有`input_encoding`參數,資料`(data)`會是一個Buffer然後`input_encoding`會被忽略

`output_encoding`參數制定了加密資料輸出的編碼格式,可以是`'binary'`、`'base64'`或`'hex'`
如果`output_encoding`被指定了,則return指定編碼的相符字串,否則return一個Buffer

`cipher.update()`方法可以在cipher.final()使用前多次呼叫,如果在cipher.final()後使用會丟出錯誤

## Class: Decipher
`Deipher`類別常用於對資料進行解密,這個類別主要有兩個使用方式:
- 包裝成一個可以讀寫的stream,能寫入未加密資料或讀出加密資料
- 用decipher.update()或decipher.final()方法產生加密資料
crypto.createDecipher() 或 crypto.createDecipheriv()方法常用於創`Decipher`的實例,`Decipher`的物件不能使用`new`來創建

例:用`Decipher`物件封裝成stream:
```javascript
const crypto = require('crypto');
const decipher = crypto.createDecipher('aes192', 'a password');

var decrypted = '';
decipher.on('readable', () => {
var data = decipher.read();
if (data)
decrypted += data.toString('utf8');
});
decipher.on('end', () => {
console.log(decrypted);
// Prints: some clear text data
});

var encrypted = 'ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504';
decipher.write(encrypted, 'hex');
decipher.end();
```

例:使用`Decipher`和piped stream:
```javascript
const crypto = require('crypto');
const fs = require('fs');
const decipher = crypto.createDecipher('aes192', 'a password');

const input = fs.createReadStream('test.enc');
const output = fs.createWriteStream('test.js');

input.pipe(decipher).pipe(output);
```

例:使用decipher.update()和decipher.final()方法:
```javascript
const crypto = require('crypto');
const decipher = crypto.createDecipher('aes192', 'a password');

var encrypted = 'ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504';
var decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted);
// Prints: some clear text data
```

### decipher.final([output_encoding])
return剩餘的解密內容
如果`output_encoding`參數是`'binary'`、`'base64'`或`'hex'`中的一種,則返回一個字串
如果沒有提供`output_encoding`,則返回一個Buffer

一旦使用了`decipher.final()`方法後,`Decipher`物件就不能再用於加密
如果多次使用`decipher.final()`將會丟回錯誤

### decipher.setAAD(buffer)
當使用加密認證模式(目前只支援`GCM`)時,`decipher.setAAD()`方法用於輸入額外認證資料(AAD)參數的值

### decipher.setAuthTag(buffer)
當使用加密認證模式(目前只支援`GCM`)時,`decipher.getAuthTag()`方法被用來傳遞接收到的認證標籤
如果沒有認證標籤,或加密內容被篡改,decipher.final()會被回傳,表示加密內容由於認證失敗而該放棄

### decipher.setAutoPadding(auto_padding=true)
當資料加密沒有使用標準的區塊填充,使用`decipher.setAutoPadding(false)`方法可以禁用自動填充
以防止decipher.final()方法檢查和移除填充

只有在輸入的資料長度為cipher區塊大小的倍數時才能關掉自動填充功能

`decipher.setAutoPadding()`方法必須在decipher.update()方法之前使用

### decipher.update(data[, input_encoding][, output_encoding])
# Class: DiffieHellman
用在更新資料`(data)`的decipher,如果有`input_encoding`的參數,那必須是`'binary'`、`'base64'`或`'hex'`
資料`(data)`參數須是一個指定編碼格式的字串,如果沒有`input_encoding`參數,資料會是一個Buffer然後`input_encoding`會被忽略

`output_encoding`參數制定了加密資料輸出的編碼格式,可以是`'binary'`、`'ascii'`或`'utf8'`
如果`output_encoding`被指定了,則return指定編碼的相符字串,否則return一個Buffer

`decipher.update()`方法可以在decipher.final()使用前多次呼叫,如果在decipher.final()後使用會丟出錯誤

## Class: DiffieHellman
### diffieHellman.computeSecret(other_public_key[, input_encoding][, output_encoding])
### diffieHellman.generateKeys([encoding])
### diffieHellman.getGenerator([encoding])
Expand All @@ -110,26 +330,26 @@
### diffieHellman.setPrivateKey(private_key[, encoding])
### diffieHellman.setPublicKey(public_key[, encoding])
### diffieHellman.verifyError
# Class: ECDH
## Class: ECDH
### ecdh.computeSecret(other_public_key[, input_encoding][, output_encoding])
### ecdh.generateKeys([encoding[, format]])
### ecdh.getPrivateKey([encoding])
### ecdh.getPublicKey([encoding[, format]])
### ecdh.setPrivateKey(private_key[, encoding])
### ecdh.setPublicKey(public_key[, encoding])
# Class: Hash
## Class: Hash
### hash.digest([encoding])
### hash.update(data[, input_encoding])
# Class: Hmac
## Class: Hmac
### hmac.digest([encoding])
### hmac.update(data[, input_encoding])
# Class: Sign
## Class: Sign
### sign.sign(private_key[, output_format])
### sign.update(data[, input_encoding])
# Class: Verify
## Class: Verify
### verifier.update(data[, input_encoding])
### verifier.verify(object, signature[, signature_format])
# crypto module methods and properties
## crypto module methods and properties
### crypto.DEFAULT_ENCODING
### crypto.fips
### crypto.createCipher(algorithm, password)
Expand Down Expand Up @@ -157,6 +377,6 @@
### crypto.randomBytes(size[, callback])
### crypto.setEngine(engine[, flags])
# Notes
### Legacy Streams API (pre Node.js v0.10)
### Recent ECDH Changes
### Support for weak or compromised algorithms
## Legacy Streams API (pre Node.js v0.10)
## Recent ECDH Changes
## Support for weak or compromised algorithms
61 changes: 60 additions & 1 deletion nodejs-V5110-Doc/DNS/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,70 @@


# DNS
```javascript
var dns = require("dns")
```
# dns.getServers()
- 以字串的方式回傳當前DNS的IP。

==

# dns.lookup(hostname[, options], callback)
- 將網域名稱解析為A(IPv4)或AAAA(IPv6)
- options包含3個參數(family, hints, all)
- family-只能為整數4或6,沒提供的話IPv4,IPv6都是有效的。
- hints-如果提供,必須是一個或多個支持的`getaddrinfo`標示。
- all-Boolean,如果true,將以陣列的方式回傳所有解析的IP,false的話只會回傳一個IP,預設為false。


==

### Supported getaddrinfo flags

==

# dns.lookupService(address, port, callback)
- 將傳入的IP和PORT號轉成網域名稱跟服務。
```javascript
var dns = require('dns')
dns.lookupService("8.8.8.8", 22, function(err, hostname, service) {
console.log('主機:%s,服務:%s',hostname,service);
})
#結果:主機:google-public-dns-a.google.com,服務:ssh
```

==

# dns.resolve(hostname[, rrtype], callback)
- 網域名稱轉IP
- rrtype:
- A:IPv4,預設.
- AAAA:IPv6.
- MX:郵件交換紀錄.
- TXT:text紀錄.
- SRV:SRV紀錄.
- PTR:用來IP找網域名稱.
- NS:域名服務器紀錄.
- CNAME:別名紀錄.
- SOA: 查詢權威紀錄.
- nsname
- hostmaster
- serial
- refresh
- retry
- expire
- minttl
```javascript
var dns = require('dns')
dns.resolve('www.google.com.tw', rrtype = 'A', function(err, addresses) {
console.log('IP:%s',JSON.stringify(addresses));
})
#結果:IP:["203.211.0.44","203.211.0.50","203.211.0.30","203.211.0.40","203.211.0.49","203.211.0.59","203.211.0.24","203.211.0.34","203.211.0.39","203.211.0.20","203.211.0.35","203.211.0.45","203.211.0.54","203.211.0.29","203.211.0.25","203.211.0.55"]

```

==

# dns.resolve4(hostname, callback)
# dns.resolve6(hostname, callback)
# dns.resolveCname(hostname, callback)
Expand All @@ -44,4 +103,4 @@
# Error codes
# Implementation considerations
### dns.lookup()
### dns.resolve(), dns.resolve*() and dns.reverse()
### dns.resolve(), dns.resolve*() and dns.reverse()
Loading