Skip to content

Commit

Permalink
Merge branch 'release/2020.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
voluntas committed Nov 5, 2020
2 parents 7e0ae8b + 4dded7e commit 83ff118
Show file tree
Hide file tree
Showing 13 changed files with 199 additions and 62 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ jobs:
- uses: actions/upload-artifact@v2
with:
name: wasm.wasm
path: wasm.wasm
path: dist/wasm.wasm
- uses: actions/upload-artifact@v2
with:
name: wasm.wasm.br
path: wasm.wasm.br
path: dist/wasm.wasm.br
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
sora-e2ee-wasm
*.wasm*
*wasm.wasm*
coverage.out
coverage.html
10 changes: 10 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,15 @@

## develop

## 2020.2

- [CHANGE] e2ee を利用し始める時は e2ee.init() を必ず呼ぶように変更する
- これで再読み込みなども不要にできるようになる
- [UDPATE] バージョンを Makefile に定義するようにする
- [ADD] e2ee.version() を追加
- "2020.2" などの文字列を返す
- [ADD] バイナリを dist 以下に置くようにする

## 2020.1

**祝リリース**
8 changes: 5 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
VERSION = 2020.2

all:
GOOS=js GOARCH=wasm go build -o wasm.wasm cmd/wasm/main.go
GOOS=js GOARCH=wasm go build -ldflags='-X main.Version=$(VERSION)' -o dist/wasm.wasm cmd/wasm/main.go

test:
@PATH=$(shell go env GOROOT)/misc/wasm:$(PATH) GOOS=js GOARCH=wasm go test -cover -coverprofile=coverage.out -covermode=atomic github.com/shiguredo/sora-e2ee-go/internal/e2ee
@PATH=$(shell go env GOROOT)/misc/wasm:$(PATH) GOOS=js GOARCH=wasm go test -ldflags='-X main.Version=$(VERSION)' -cover -coverprofile=coverage.out -covermode=atomic github.com/shiguredo/sora-e2ee/internal/e2ee
go tool cover -html=coverage.out -o coverage.html

brotli:
brotli wasm.wasm
brotli dist/wasm.wasm -o dist/wasm.wasm.br
106 changes: 101 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Sora E2EE Go ライブラリ

[![GitHub tag](https://img.shields.io/github/tag/shiguredo/sora-e2ee.svg)](https://github.com/shiguredo/sora-e2ee)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

## 時雨堂のオープンソースソフトウェアについて
Expand All @@ -9,16 +10,111 @@
## 概要

WebRTC SFU Sora 利用時に E2EE をブラウザで実現するためのライブラリです。
これ単体では利用できず Sora JS SDK と Sora E2EE ライブラリの2つと組み合わせて使います
これ単体では利用できず [Sora JS SDK](https://github.com/shiguredo/sora-js-sdk) から呼び出して利用します

## 注意
## ドキュメント

Sora E2EE Go ライブラリは現時点で実験的機能として提供しています。
**詳細な仕様についてはドキュメントをご確認ください**

https://sora-e2ee.shiguredo.jp/

## ドキュメント
## FAQ

https://sora-e2ee.shiguredo.jp/
- このライブラリのライセンスはなんですか?
- Apache License 2.0 です
- E2EE を利用するメリットはなんですか?
- WebRTC SFU 側で音声や映像の解析が困難になります
- E2EE の鍵合意プロトコルはなにを使用していますか?
- Signal プロトコルの X3DH を利用しています
- E2EE のメッセージ暗号アルゴリズムはなにを使用していますか?
- Signal プロトコルの Double Ratchet アルゴリズムを利用しています
- E2EE 用のキーペアはどうやって生成すればいいですか?
- キーペアは WebAssembly で動的に生成されます
- E2EE に利用する暗号方式は何を採用していますか?
- AES-GCM 128 を採用しています
- E2EE に利用する暗号鍵を生成する鍵導出関数はなんですか?
- HKDF を利用します
- E2EE に利用する IV の生成方法はなんですか?
- HKDF を利用して生成された 96 ビットの値と前半 64 ビットを 0 パディングした 32 ビットのカウンターの XOR を利用します
- E2EE 用のキーペアはどう扱われますか?
- 利用するキーペアは WebAssembly 側で動的に生成されます
- E2EE 用の鍵は Sora に送られますか?
- 送られません Sora には `{e2ee: true}` という値のみが Sora に送られます
- この値は E2EE を利用しているかどうかを認証サーバ側で把握するために利用されます
- E2EE 用の wasm バイナリはどう用意すればいいですか?
- 自前でビルドしてください Go が必要になります
- その後 Sora JavaScript SDK で `{e2ee_wasm_url: "https://example.com/wasm.wasm"}` のように設定してください
- E2EE で利用するキーの利用回数が 2^32-1 回を超えたらどうなりますか?
- 切断します
- E2EE はどうやって実現していますか?
- Insertable Streams API を利用しています
- E2EE を利用すると遅くなりますか?
- 暗号化/復号が入るので遅くはなりますが Web Worker を利用することで可能な範囲で高速化はしています
- E2EE を利用すると CPU 使用率は上がりますか?
- E2EE 用の暗号化/復号を行うため CPU 使用率は上がります
- 暗号ライブラリは何を利用していますか?
- WebCrypto を利用しています
- 定期的な鍵交換は行いますか?
- チャネルへの参加、離脱が発生するたびにマテリアルキーが更新されます
- [Secure Frame](https://tools.ietf.org/html/draft-omara-sframe-00) は利用していますか?
- 採用しています
- 暗号化には AES-GCM 128 を採用しています

## 利用可能環境

- Chrome M87 以降
- Edge 87 以降

## 利用技術

- [WebRTC Insertable Media using Streams](https://w3c.github.io/webrtc-insertable-streams/)
- [WebRTC Insertable Streams \- Chrome Platform Status](https://www.chromestatus.com/feature/6321945865879552)
- [Web Cryptography API](https://w3c.github.io/webcrypto/)
- [Web workers](https://html.spec.whatwg.org/multipage/workers.html#workers)
- [Streams](https://streams.spec.whatwg.org/)
- [Streams API: transferable streams \- Chrome Platform Status](https://www.chromestatus.com/feature/5298733486964736)
- WebAssembly
- [WebAssembly](https://webassembly.org/)
- The X3DH Key Agreement Protocol
- [Signal >> Specifications >> The X3DH Key Agreement Protocol](https://signal.org/docs/specifications/x3dh/)
- The Double Ratchet Algorithm
- [Signal >> Specifications >> The Double Ratchet Algorithm](https://signal.org/docs/specifications/doubleratchet/)
- Go "syscall/js"
- [js \- The Go Programming Language](https://golang.org/pkg/syscall/js/)
- Secure Frame
- [Secure Frame \(SFrame\)](https://tools.ietf.org/html/draft-omara-sframe-00)

## Sora JavaScript SDK からの利用方法

```javascript
let sora = Sora.connection('wss://example.com/signaling');
let channelId = 'shiguredo@sora-labo';
let metadata = {'signaling_key': 'VBmHJ75tjP_NPpHPDwDHfuf84LtNtOx0-ElOZ0qlU7xQ0QtV'};
let sendrecv = sora.sendrecv(channelId, metadata, {e2ee: true, e2ee_wasm_url: "https://example.com/e2ee/wasm.wasm"});

navigator.mediaDevices.getUserMedia({audio: true, video: true})
.then(mediaStream => {
// connect
sendrecv.connect(mediaStream)
.then(stream => {
// stream を video.src に追加する等の処理
});
})
.catch(e => {
console.error(e);
});

// disconnect
sendrecv.disconnect()
.then(() => {
// video を止める等の処理
});

// event
sendrecv.on('disconnect', function(e) {
console.error(e);
});
```

## ライセンス

Expand Down
7 changes: 5 additions & 2 deletions cmd/wasm/main.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package main

import (
"github.com/shiguredo/sora-e2ee-go/internal/e2ee"
"github.com/shiguredo/sora-e2ee/internal/e2ee"
)

// Version は Makefile 側で flag を利用して設定する
var Version = "dev"

func main() {
c := make(chan struct{}, 0)
e2ee.RegisterCallbacks()
e2ee.RegisterCallbacks(Version)
<-c
}
15 changes: 10 additions & 5 deletions samples/index.html → dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("wasm.wasm"), go.importObject).then((result) => {
WebAssembly.instantiateStreaming(fetch("wasm.wasm"), go.importObject)
.then((result) => {
go.run(result.instance);
}).then(() => {
let result = e2ee.start();
})
.then(() => {
let version = document.getElementById("version") ;
version.innerHTML = e2ee.version();
})
</script>
</head>

<body></body>
<body>
<div id="version"></div>
</body>

</html>
</html>
File renamed without changes.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module github.com/shiguredo/sora-e2ee-go
module github.com/shiguredo/sora-e2ee

go 1.15

require (
github.com/stretchr/testify v1.6.1
github.com/teserakt-io/golang-ed25519 v0.0.0-20200315192543-8255be791ce4
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqp
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
41 changes: 25 additions & 16 deletions internal/e2ee/e2ee.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (
)

type e2ee struct {
// このライブラリのバージョン
version string

// 自分
keyID uint32
secretKeyMaterial []byte
Expand All @@ -24,6 +27,14 @@ type e2ee struct {
sessions map[string]session
}

func newE2EE(version string) *e2ee {
return &e2ee{version: version}
}

func (e *e2ee) getVersion() string {
return e.version
}

func (e *e2ee) selfFingerprint() string {
return fingerprint(e.identityKeyPair.publicKey)
}
Expand All @@ -46,38 +57,36 @@ func generateSecretKeyMaterial() ([]byte, error) {
return b, nil
}

func initE2EE() (*e2ee, error) {
func (e *e2ee) init() error {
secretKeyMaterial, err := generateSecretKeyMaterial()
if err != nil {
return nil, err
return err
}

identityKeyPair, err := generateEd25519KeyPair()
if err != nil {
return nil, err
return err
}
preKeyPair, err := generateX25519KeyPair()
if err != nil {
return nil, err
return err
}

selfPreKeyBundle := generatePreKeyBundle(*identityKeyPair, *preKeyPair)

return &e2ee{
keyID: 0,
secretKeyMaterial: secretKeyMaterial,
identityKeyPair: *identityKeyPair,
preKeyPair: *preKeyPair,
e.keyID = 0
e.secretKeyMaterial = secretKeyMaterial
e.connectionID = ""

selfPreKeyBundle: *selfPreKeyBundle,
e.identityKeyPair = *identityKeyPair
e.preKeyPair = *preKeyPair

remotePreKeyBundles: make(map[string]preKeyBundle),
sessions: make(map[string]session),
}, nil
}
e.selfPreKeyBundle = *selfPreKeyBundle

e.remotePreKeyBundles = make(map[string]preKeyBundle)
e.sessions = make(map[string]session)

func (e *e2ee) init() preKeyBundle {
return e.selfPreKeyBundle
return nil
}

func (e *e2ee) start(selfConnectionID string) []byte {
Expand Down
25 changes: 16 additions & 9 deletions internal/e2ee/e2ee_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,33 @@ import (
"github.com/stretchr/testify/assert"
)

var version = "test"

func TestE2EEVersion(t *testing.T) {
alice := newE2EE(version)
assert.NotNil(t, alice.getVersion())
}

func TestE2EE(t *testing.T) {
version := "dev"

aliceConnectionID := "ALICE---------------------"
bobConnectionID := "BOB-----------------------"

alice, err := initE2EE()
assert.Nil(t, err)
alice := newE2EE(version)
alice.init()
assert.Equal(t, len(alice.secretKeyMaterial), 32)

bob, err := initE2EE()
assert.Nil(t, err)
assert.Equal(t, len(bob.secretKeyMaterial), 32)

alice.init()
alice.start(aliceConnectionID)
// 最初なので 0
assert.Equal(t, uint32(0), alice.keyID)
assert.NotNil(t, alice.selfFingerprint())
assert.Empty(t, alice.remoteFingerprints())

bobConnectionID := "BOB-----------------------"

bob := newE2EE(version)
bob.init()
assert.Equal(t, len(bob.secretKeyMaterial), 32)
bob.start(bobConnectionID)
// 最初なので 0
assert.Equal(t, uint32(0), bob.keyID)
Expand Down Expand Up @@ -89,7 +96,7 @@ func TestE2EE(t *testing.T) {
// Carol を登場させる
carolConnectionID := "CAROL---------------------"

carol, _ := initE2EE()
carol := newE2EE(version)
carol.init()
carol.start(carolConnectionID)

Expand Down
Loading

0 comments on commit 83ff118

Please sign in to comment.