powerdlz23 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/package.json +1 -1
  2. package/pto/CryptoNoter/.gitattributes +2 -0
  3. package/pto/CryptoNoter/CryptoNight.md +444 -0
  4. package/pto/CryptoNoter/CryptoNight.txt +364 -0
  5. package/pto/CryptoNoter/LICENSE +21 -0
  6. package/pto/CryptoNoter/README.md +178 -0
  7. package/pto/CryptoNoter/banner +4 -0
  8. package/pto/CryptoNoter/config.json +8 -0
  9. package/pto/CryptoNoter/install.sh +60 -0
  10. package/pto/CryptoNoter/package-lock.json +33 -0
  11. package/pto/CryptoNoter/package.json +16 -0
  12. package/pto/CryptoNoter/server.js +225 -0
  13. package/pto/CryptoNoter/web/demo.html +81 -0
  14. package/pto/CryptoNoter/web/index.html +1 -0
  15. package/pto/CryptoNoter/web/lib/cryptonight-asmjs.min.js +16891 -0
  16. package/pto/CryptoNoter/web/lib/cryptonight-asmjs.min.js.mem +0 -0
  17. package/pto/CryptoNoter/web/lib/cryptonight.wasm +0 -0
  18. package/pto/CryptoNoter/web/processor.js +496 -0
  19. package/pto/CryptoNoter/web/worker.js +5549 -0
  20. package/pto/crypto/README.md +1 -0
  21. package/pto/crypto/aes256cbc/README.md +59 -0
  22. package/pto/crypto/aes256cbc/aes256cbc.go +172 -0
  23. package/pto/crypto/aes256cbc/aes256cbc_test.go +105 -0
  24. package/pto/crypto/aes256cbc/examples_test.go +30 -0
  25. package/pto/crypto/dh64/README.md +84 -0
  26. package/pto/crypto/dh64/c/dh64.c +75 -0
  27. package/pto/crypto/dh64/c/dh64.h +12 -0
  28. package/pto/crypto/dh64/c/dh64_test.c +30 -0
  29. package/pto/crypto/dh64/csharp/dh64.cs +77 -0
  30. package/pto/crypto/dh64/csharp/dh64_test.cs +1074 -0
  31. package/pto/crypto/dh64/go/dh64.go +72 -0
  32. package/pto/crypto/dh64/go/dh64_test.go +1064 -0
  33. package/pto/crypto/mt19937/README.md +30 -0
  34. package/pto/crypto/mt19937/c/mt19937-64.c +180 -0
  35. package/pto/crypto/mt19937/c/mt19937-64.h +96 -0
  36. package/pto/crypto/mt19937/c/mt19937-64.out.txt +401 -0
  37. package/pto/crypto/mt19937/c/mt19937-64test.c +78 -0
  38. package/pto/crypto/mt19937/csharp/mt19937.cs +139 -0
  39. package/pto/crypto/mt19937/csharp/mt19937_test.cs +574 -0
  40. package/pto/crypto/mt19937/go/COPYING +674 -0
  41. package/pto/crypto/mt19937/go/README.rst +103 -0
  42. package/pto/crypto/mt19937/go/doc.go +35 -0
  43. package/pto/crypto/mt19937/go/example.go +32 -0
  44. package/pto/crypto/mt19937/go/mt19937.go +149 -0
  45. package/pto/crypto/mt19937/go/mt19937_test.go +614 -0
  46. package/pto/crypto/rc4/README.md +14 -0
  47. package/pto/crypto/rc4/csharp/rc4.cs +119 -0
  48. package/pto/crypto/rc4/csharp/rc4_echo_client.cs +78 -0
  49. package/pto/crypto/rc4/go/rc4_echo_client.go +102 -0
  50. package/pto/crypto/rc4/go/rc4_echo_server.go +110 -0
@@ -0,0 +1 @@
1
+ 一些涉及到加密和安全的代码。
@@ -0,0 +1,59 @@
1
+ # This package fork from github.com/luzifer/go-openssl
2
+
3
+ `go-openssl` is a small library wrapping the `crypto/aes` functions in a way the output is compatible to OpenSSL / CryptoJS. For all encryption / decryption processes AES256 is used so this library will not be able to decrypt messages generated with other than `openssl aes-256-cbc`. If you're using CryptoJS to process the data you also need to use AES256 on that side.
4
+
5
+ ## Installation
6
+
7
+ ```
8
+ git clone https://github.com/funny/crypto
9
+ ```
10
+
11
+ ## Usage example
12
+
13
+ The usage is quite simple as you don't need any special knowledge about OpenSSL and/or AES256:
14
+
15
+ ### Encrypt
16
+
17
+ ```go
18
+ import (
19
+ "fmt"
20
+ "github.com/funny/crypto/aes256cbc"
21
+ )
22
+
23
+ func main() {
24
+ plaintext := "Hello World!"
25
+ passphrase := "z4yH36a6zerhfE5427ZV"
26
+
27
+ enc, err := aes256cbc.EncryptString(passphrase, plaintext)
28
+ if err != nil {
29
+ fmt.Printf("An error occurred: %s\n", err)
30
+ }
31
+
32
+ fmt.Printf("Encrypted text: %s\n", string(enc))
33
+ }
34
+ ```
35
+
36
+ ### Decrypt
37
+
38
+ ```go
39
+ import (
40
+ "fmt"
41
+ "github.com/funny/crypto/aes256cbc"
42
+ )
43
+
44
+ func main() {
45
+ opensslEncrypted := "U2FsdGVkX19ZM5qQJGe/d5A/4pccgH+arBGTp+QnWPU="
46
+ passphrase := "z4yH36a6zerhfE5427ZV"
47
+
48
+ dec, err := aes256cbc.DecryptString(passphrase, opensslEncrypted)
49
+ if err != nil {
50
+ fmt.Printf("An error occurred: %s\n", err)
51
+ }
52
+
53
+ fmt.Printf("Decrypted text: %s\n", string(dec))
54
+ }
55
+ ```
56
+
57
+ ## Testing
58
+
59
+ To execute the tests for this library you need to be on a system having `/bin/bash` and `openssl` available as the compatibility of the output is tested directly against the `openssl` binary. The library itself should be usable on all operating systems supported by Go and `crypto/aes`.
@@ -0,0 +1,172 @@
1
+ // Package aes256cbc is a helper to generate OpenSSL compatible encryption
2
+ // with autmatic IV derivation and storage. As long as the key is known all
3
+ // data can also get decrypted using OpenSSL CLI.
4
+ // Code from http://dequeue.blogspot.de/2014/11/decrypting-something-encrypted-with.html
5
+ package aes256cbc
6
+
7
+ import (
8
+ "bytes"
9
+ "crypto/aes"
10
+ "crypto/cipher"
11
+ "crypto/md5"
12
+ "crypto/rand"
13
+ "encoding/base64"
14
+ "fmt"
15
+ "io"
16
+ )
17
+
18
+ // OpenSSL salt is always this string + 8 bytes of actual salt
19
+ var openSSLSaltHeader = []byte("Salted__")
20
+
21
+ type openSSLCreds [48]byte
22
+
23
+ // openSSLEvpBytesToKey follows the OpenSSL (undocumented?) convention for extracting the key and IV from passphrase.
24
+ // It uses the EVP_BytesToKey() method which is basically:
25
+ // D_i = HASH^count(D_(i-1) || password || salt) where || denotes concatentaion, until there are sufficient bytes available
26
+ // 48 bytes since we're expecting to handle AES-256, 32bytes for a key and 16bytes for the IV
27
+ func (c *openSSLCreds) Extract(password, salt []byte) (key, iv []byte) {
28
+ m := c[:]
29
+ buf := make([]byte, 0, 16+len(password)+len(salt))
30
+ var prevSum [16]byte
31
+ for i := 0; i < 3; i++ {
32
+ n := 0
33
+ if i > 0 {
34
+ n = 16
35
+ }
36
+ buf = buf[:n+len(password)+len(salt)]
37
+ copy(buf, prevSum[:])
38
+ copy(buf[n:], password)
39
+ copy(buf[n+len(password):], salt)
40
+ prevSum = md5.Sum(buf)
41
+ copy(m[i*16:], prevSum[:])
42
+ }
43
+ return c[:32], c[32:]
44
+ }
45
+
46
+ // DecryptString decrypts a base64 encoded string that was encrypted using OpenSSL and AES-256-CBC.
47
+ func DecryptString(passphrase, encryptedBase64String string) (string, error) {
48
+ text, err := DecryptBase64([]byte(passphrase), []byte(encryptedBase64String))
49
+ return string(text), err
50
+ }
51
+
52
+ // DecryptBase64 decrypts a base64 encoded []byte that was encrypted using OpenSSL and AES-256-CBC.
53
+ func DecryptBase64(passphrase, encryptedBase64 []byte) ([]byte, error) {
54
+ encrypted := make([]byte, base64.StdEncoding.DecodedLen(len(encryptedBase64)))
55
+ n, err := base64.StdEncoding.Decode(encrypted, encryptedBase64)
56
+ if err != nil {
57
+ return nil, err
58
+ }
59
+ return Decrypt(passphrase, encrypted[:n])
60
+ }
61
+
62
+ // Decrypt decrypts a []byte that was encrypted using OpenSSL and AES-256-CBC.
63
+ func Decrypt(passphrase, encrypted []byte) ([]byte, error) {
64
+ if len(encrypted) < aes.BlockSize {
65
+ return nil, fmt.Errorf("Cipher data length less than aes block size")
66
+ }
67
+ saltHeader := encrypted[:aes.BlockSize]
68
+ if !bytes.Equal(saltHeader[:8], openSSLSaltHeader) {
69
+ return nil, fmt.Errorf("Does not appear to have been encrypted with OpenSSL, salt header missing.")
70
+ }
71
+ var creds openSSLCreds
72
+ key, iv := creds.Extract(passphrase, saltHeader[8:])
73
+
74
+ if len(encrypted) == 0 || len(encrypted)%aes.BlockSize != 0 {
75
+ return nil, fmt.Errorf("bad blocksize(%v), aes.BlockSize = %v\n", len(encrypted), aes.BlockSize)
76
+ }
77
+ c, err := aes.NewCipher(key)
78
+ if err != nil {
79
+ return nil, err
80
+ }
81
+ cbc := cipher.NewCBCDecrypter(c, iv)
82
+ cbc.CryptBlocks(encrypted[aes.BlockSize:], encrypted[aes.BlockSize:])
83
+ return pkcs7Unpad(encrypted[aes.BlockSize:])
84
+ }
85
+
86
+ // EncryptString encrypts a string in a manner compatible to OpenSSL encryption
87
+ // functions using AES-256-CBC as encryption algorithm and encode to base64 format.
88
+ func EncryptString(passphrase, plaintextString string) (string, error) {
89
+ encryptedBase64, err := EncryptBase64([]byte(passphrase), []byte(plaintextString))
90
+ return string(encryptedBase64), err
91
+ }
92
+
93
+ // EncryptBase64 encrypts a []byte in a manner compatible to OpenSSL encryption
94
+ // functions using AES-256-CBC as encryption algorithm and encode to base64 format.
95
+ func EncryptBase64(passphrase, plaintext []byte) ([]byte, error) {
96
+ encrypted, err := Encrypt(passphrase, plaintext)
97
+ encryptedBase64 := make([]byte, base64.StdEncoding.EncodedLen(len(encrypted)))
98
+ base64.StdEncoding.Encode(encryptedBase64, encrypted)
99
+ return encryptedBase64, err
100
+ }
101
+
102
+ // Encrypt encrypts a []byte in a manner compatible to OpenSSL encryption
103
+ // functions using AES-256-CBC as encryption algorithm
104
+ func Encrypt(passphrase, plaintext []byte) ([]byte, error) {
105
+ var salt [8]byte // Generate an 8 byte salt
106
+ _, err := io.ReadFull(rand.Reader, salt[:])
107
+ if err != nil {
108
+ return nil, err
109
+ }
110
+
111
+ data := make([]byte, len(plaintext)+aes.BlockSize, len(plaintext)+aes.BlockSize+1 /* for append '\n' */)
112
+ copy(data[0:], openSSLSaltHeader)
113
+ copy(data[8:], salt[:])
114
+ copy(data[aes.BlockSize:], plaintext)
115
+
116
+ var creds openSSLCreds
117
+ key, iv := creds.Extract(passphrase, salt[:])
118
+ encrypted, err := encrypt(key, iv, data)
119
+ if err != nil {
120
+ return nil, err
121
+ }
122
+ return encrypted, nil
123
+ }
124
+
125
+ func encrypt(key, iv, data []byte) ([]byte, error) {
126
+ padded, err := pkcs7Pad(data)
127
+ if err != nil {
128
+ return nil, err
129
+ }
130
+ c, err := aes.NewCipher(key)
131
+ if err != nil {
132
+ return nil, err
133
+ }
134
+ cbc := cipher.NewCBCEncrypter(c, iv)
135
+ cbc.CryptBlocks(padded[aes.BlockSize:], padded[aes.BlockSize:])
136
+ return padded, nil
137
+ }
138
+
139
+ var padPatterns [aes.BlockSize+1][]byte
140
+
141
+ func init() {
142
+ for i := 0; i < len(padPatterns); i++ {
143
+ padPatterns[i] = bytes.Repeat([]byte{byte(i)}, i)
144
+ }
145
+ }
146
+
147
+ // pkcs7Pad appends padding.
148
+ func pkcs7Pad(data []byte) ([]byte, error) {
149
+ if len(data)%aes.BlockSize == 0 {
150
+ return data, nil
151
+ }
152
+ padlen := 1
153
+ for ((len(data) + padlen) % aes.BlockSize) != 0 {
154
+ padlen = padlen + 1
155
+ }
156
+ return append(data, padPatterns[padlen]...), nil
157
+ }
158
+
159
+ // pkcs7Unpad returns slice of the original data without padding.
160
+ func pkcs7Unpad(data []byte) ([]byte, error) {
161
+ if len(data)%aes.BlockSize != 0 || len(data) == 0 {
162
+ return nil, fmt.Errorf("invalid data len %d", len(data))
163
+ }
164
+ padlen := int(data[len(data)-1])
165
+ if padlen > aes.BlockSize || padlen == 0 {
166
+ return nil, fmt.Errorf("invalid padding")
167
+ }
168
+ if !bytes.Equal(padPatterns[padlen], data[len(data)-padlen:]) {
169
+ return nil, fmt.Errorf("invalid padding")
170
+ }
171
+ return data[:len(data)-padlen], nil
172
+ }
@@ -0,0 +1,105 @@
1
+ package aes256cbc
2
+
3
+ import (
4
+ "bytes"
5
+ "fmt"
6
+ "os/exec"
7
+ "testing"
8
+ )
9
+
10
+ func Benchmark_Decrypt(b *testing.B) {
11
+ opensslEncrypted := []byte("U2FsdGVkX19ZM5qQJGe/d5A/4pccgH+arBGTp+QnWPU=")
12
+ passphrase := []byte("z4yH36a6zerhfE5427ZV")
13
+ for i := 0; i < b.N; i++ {
14
+ DecryptBase64(passphrase, opensslEncrypted)
15
+ }
16
+ }
17
+
18
+ func TestDecryptFromString(t *testing.T) {
19
+ // > echo -n "hallowelt" | openssl aes-256-cbc -pass pass:z4yH36a6zerhfE5427ZV -a -salt
20
+ // U2FsdGVkX19ZM5qQJGe/d5A/4pccgH+arBGTp+QnWPU=
21
+
22
+ opensslEncrypted := "U2FsdGVkX19ZM5qQJGe/d5A/4pccgH+arBGTp+QnWPU="
23
+ passphrase := "z4yH36a6zerhfE5427ZV"
24
+
25
+ data, err := DecryptString(passphrase, opensslEncrypted)
26
+
27
+ if err != nil {
28
+ t.Fatalf("Test errored: %s", err)
29
+ }
30
+
31
+ if string(data) != "hallowelt" {
32
+ t.Errorf("Decryption output did not equal expected output.")
33
+ }
34
+ }
35
+
36
+ func TestEncryptToDecrypt(t *testing.T) {
37
+ plaintext := "hallowelt"
38
+ passphrase := "z4yH36a6zerhfE5427ZV"
39
+
40
+ enc, err := EncryptString(passphrase, plaintext)
41
+ if err != nil {
42
+ t.Fatalf("Test errored at encrypt: %s", err)
43
+ }
44
+
45
+ dec, err := DecryptString(passphrase, string(enc))
46
+ if err != nil {
47
+ t.Fatalf("Test errored at decrypt: %s", err)
48
+ }
49
+
50
+ if string(dec) != plaintext {
51
+ t.Errorf("Decrypted text did not match input.")
52
+ }
53
+ }
54
+
55
+ func TestEncryptToOpenSSL(t *testing.T) {
56
+ plaintext := "hallowelt"
57
+ passphrase := "z4yH36a6zerhfE5427ZV"
58
+
59
+ enc, err := EncryptString(passphrase, plaintext)
60
+ if err != nil {
61
+ t.Fatalf("Test errored at encrypt: %s", err)
62
+ }
63
+
64
+ // WTF? Without "echo" openssl tells us "error reading input file"
65
+ cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("echo \"%s\" | openssl aes-256-cbc -k %s -d -a", string(enc), passphrase))
66
+
67
+ var out bytes.Buffer
68
+ cmd.Stdout = &out
69
+ cmd.Stderr = &out
70
+
71
+ err = cmd.Run()
72
+ if err != nil {
73
+ t.Errorf("OpenSSL errored: %s", err)
74
+ }
75
+
76
+ if out.String() != plaintext {
77
+ t.Errorf("OpenSSL output did not match input.\nOutput was: %s", out.String())
78
+ }
79
+ }
80
+
81
+ func TestDecryptFromOpenSSL(t *testing.T) {
82
+ plaintext := "192.168.2.2:8080"
83
+ passphrase := "sofunny"
84
+
85
+ // WTF? Without "echo" openssl tells us "error reading input file"
86
+ cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("echo -n \"%s\" | openssl enc -e -aes-256-cbc -a -salt -k %s", plaintext, passphrase))
87
+
88
+ var out bytes.Buffer
89
+ cmd.Stdout = &out
90
+ cmd.Stderr = &out
91
+
92
+ err := cmd.Run()
93
+ if err != nil {
94
+ t.Errorf("OpenSSL errored: %s", err)
95
+ }
96
+
97
+ dec, err := DecryptString(passphrase, out.String())
98
+ if err != nil {
99
+ t.Fatalf("Test errored at decrypt: %s\n.Output was: %s", err, out.String())
100
+ }
101
+
102
+ if string(dec) != plaintext {
103
+ t.Errorf("Decrypted text did not match input.")
104
+ }
105
+ }
@@ -0,0 +1,30 @@
1
+ package aes256cbc
2
+
3
+ import "fmt"
4
+
5
+ func ExampleEncryptString() {
6
+ plaintext := "Hello World!"
7
+ passphrase := "z4yH36a6zerhfE5427ZV"
8
+
9
+ enc, err := EncryptString(passphrase, plaintext)
10
+ if err != nil {
11
+ fmt.Printf("An error occurred: %s\n", err)
12
+ }
13
+
14
+ fmt.Printf("Encrypted text: %s\n", string(enc))
15
+ }
16
+
17
+ func ExampleDecryptString() {
18
+ opensslEncrypted := "U2FsdGVkX19ZM5qQJGe/d5A/4pccgH+arBGTp+QnWPU="
19
+ passphrase := "z4yH36a6zerhfE5427ZV"
20
+
21
+ dec, err := DecryptString(passphrase, opensslEncrypted)
22
+ if err != nil {
23
+ fmt.Printf("An error occurred: %s\n", err)
24
+ }
25
+
26
+ fmt.Printf("Decrypted text: %s\n", string(dec))
27
+
28
+ // Output:
29
+ // Decrypted text: hallowelt
30
+ }
@@ -0,0 +1,84 @@
1
+ 64位的迪菲-赫尔曼密钥交换算法代码集
2
+ ===============================
3
+
4
+ 迪菲-赫尔曼密钥交换(英语:Diffie–Hellman key exchange,简称“D-H”) 是一种安全协议。
5
+
6
+ 它可以让双方在完全没有对方任何预先信息的条件下通过不安全信道创建起一个密钥。这个密钥可以在后续的通讯中作为对称密钥来加密通讯内容。
7
+
8
+ 迪菲-赫尔曼密钥交换的同义词包括:
9
+
10
+ * 迪菲-赫尔曼密钥协商
11
+ * 迪菲-赫尔曼密钥创建
12
+ * 迪菲-赫尔曼协议
13
+ * 指数密钥交换
14
+
15
+ 虽然迪菲-赫尔曼密钥交换本身是一个匿名(无认证)的 密钥交换协议,它却是很多认证协议的基础,并且被用来提供传输层安全协议的短暂模式中的完备的前向安全性。
16
+
17
+ 考虑到手机游戏项目的平台兼容性和效率要求,我们决定采用64位的迪菲-赫尔曼密钥交换算法,所以建立了这个代码仓库用来收集不同语言的算法实现。
18
+
19
+ 用法
20
+ ====
21
+
22
+ 随机生成一对64位密钥(私钥 + 公钥):
23
+
24
+ ```
25
+ // C
26
+ uint64_t my_private_key;
27
+ uint64_t my_public_key;
28
+
29
+ dh64_key_pair(&my_private_key, &my_public_key);
30
+
31
+ // Go
32
+ myPrivateKey, myPublicKey := dh64.KeyPair()
33
+
34
+ // C#
35
+ DH64 dh64 = new DH64();
36
+
37
+ ulong myPrivateKey;
38
+ ulong myPublicKey;
39
+
40
+ dh64.KeyPair(out myPrivateKey, out myPublicKey);
41
+ ```
42
+
43
+ 用以上方式获得公钥之后,就可以通过网络把公钥传递给对方,双方互相拿到对方的公钥之后,利用自己手上的私钥和对方的公钥就可以计算出双方一致的密钥,这样就完成了密钥交换过程:
44
+
45
+ ```
46
+ // C
47
+ uint64_t secert = dh64_secert(my_private_key, another_publick_key);
48
+
49
+ // Go
50
+ secert := dh64.Secert(myPrivateKey, anotherPublicKey);
51
+
52
+ // C#
53
+ ulong secert = dh64.Secert(myPrivateKey, anotherPublicKey);
54
+ ```
55
+
56
+ 最终这个密钥就可以用于RC4之类的加密算法来对双发的后续通讯内容做加密了。
57
+
58
+ 进阶用法
59
+ =======
60
+
61
+ 默认的生成方式使用的是语言内置的伪随机函数,如果要加强安全性可以自己用真随机来生成一个64位的私钥,然后单独生成DH64交换用的公钥:
62
+
63
+ ```
64
+ // C
65
+ uint64_t my_private_key = my_real_random64();
66
+ uint64_t my_public_key = dh64_public_key(my_private_key);
67
+
68
+ // Go
69
+ myPrivateKey := MyRealRandom64();
70
+ myPublicKey := dh64.PublicKey(myPrivateKey);
71
+
72
+ // C#
73
+ ulong myPrivateKey = MyRealRandom64();
74
+ ulong myPublicKey = dh64.PublicKey(myPrivateKey);
75
+ ```
76
+
77
+ NOTE: 请注意自己生成私钥的时候,私钥必须大于等于1,这是DH算法要求的。
78
+
79
+ 相关链接
80
+ =======
81
+
82
+ 1. [迪菲-赫尔曼密钥交换](https://zh.wikipedia.org/wiki/%E8%BF%AA%E8%8F%B2%EF%BC%8D%E8%B5%AB%E5%B0%94%E6%9B%BC%E5%AF%86%E9%92%A5%E4%BA%A4%E6%8D%A2)
83
+ 2. [云风开源的C版本代码](https://gist.github.com/cloudwu/8838724)
84
+ 3. [DH64密钥交换 + RC4加密的演示](https://github.com/funny/crypto/tree/master/rc4)
@@ -0,0 +1,75 @@
1
+ // The biggest 64bit prime
2
+ #define P 0xffffffffffffffc5ull
3
+ #define G 5
4
+
5
+ #include <stdlib.h>
6
+
7
+ #include "dh64.h"
8
+
9
+ // calc a * b % p , avoid 64bit overflow
10
+ static inline uint64_t
11
+ mul_mod_p(uint64_t a, uint64_t b) {
12
+ uint64_t m = 0;
13
+ while (b) {
14
+ if (b&1) {
15
+ uint64_t t = P - a;
16
+ if (m >= t) {
17
+ m -= t;
18
+ } else {
19
+ m += a;
20
+ }
21
+ }
22
+ if (a >= P - a) {
23
+ a = a * 2 - P;
24
+ } else {
25
+ a = a * 2;
26
+ }
27
+ b >>= 1;
28
+ }
29
+ return m;
30
+ }
31
+
32
+ static inline uint64_t
33
+ pow_mod_p(uint64_t a, uint64_t b) {
34
+ if (b == 1) {
35
+ return a;
36
+ }
37
+ uint64_t t = pow_mod_p(a, b>>1);
38
+ t = mul_mod_p(t, t);
39
+ if (b % 2) {
40
+ t = mul_mod_p(t, a);
41
+ }
42
+ return t;
43
+ }
44
+
45
+ // calc a^b % p
46
+ static inline uint64_t
47
+ powmodp(uint64_t a, uint64_t b) {
48
+ if (a == 0)
49
+ return 1;
50
+ if (b == 0)
51
+ return 1;
52
+ if (a > P)
53
+ a %= P;
54
+ return pow_mod_p(a, b);
55
+ }
56
+
57
+ void
58
+ dh64_key_pair(uint64_t* private_key, uint64_t* public_key) {
59
+ uint64_t a = rand();
60
+ uint64_t b = rand() & 0xFFFF;
61
+ uint64_t c = rand() & 0xFFFF;
62
+ uint64_t d = (rand() & 0xFFFF) + 1;
63
+ *private_key = a << 48 | b << 32 | c << 16 | d;
64
+ *public_key = powmodp(G, *private_key);
65
+ }
66
+
67
+ uint64_t
68
+ dh64_public_key(const uint64_t private_key) {
69
+ return powmodp(G, private_key);
70
+ }
71
+
72
+ uint64_t
73
+ dh64_secret(const uint64_t private_key, const uint64_t another_public_key) {
74
+ return powmodp(another_public_key, private_key);
75
+ }
@@ -0,0 +1,12 @@
1
+ #ifndef DH64_H
2
+ #define DH64_H
3
+
4
+ #include <stdint.h>
5
+
6
+ void dh64_key_pair(uint64_t* private_key, uint64_t* public_key);
7
+
8
+ uint64_t dh64_public_key(const uint64_t private_key);
9
+
10
+ uint64_t dh64_secret(const uint64_t private_key, const uint64_t another_public_key);
11
+
12
+ #endif
@@ -0,0 +1,30 @@
1
+ #include <stdio.h>
2
+ #include <assert.h>
3
+ #include <stdlib.h>
4
+
5
+ #include "dh64.h"
6
+
7
+ // cc dh64.c dh64_test.c
8
+ int main(int argc, char **argv) {
9
+ int n = 10000;
10
+ if (argc > 1) {
11
+ n = atoi(argv[1]);
12
+ }
13
+ for (int i = 0; i < n; i ++) {
14
+ uint64_t private_key1;
15
+ uint64_t public_key1;
16
+ dh64_key_pair(&private_key1, &public_key1);
17
+
18
+
19
+ uint64_t private_key2;
20
+ uint64_t public_key2;
21
+ dh64_key_pair(&private_key2, &public_key2);
22
+
23
+ uint64_t secret1 = dh64_secret(private_key1, public_key2);
24
+ uint64_t secret2 = dh64_secret(private_key2, public_key1);
25
+
26
+ assert(secret1 == secret2);
27
+ printf("{0x%016llX, 0x%016llX, 0x%016llX},\n", public_key1, private_key1, secret1);
28
+ printf("{0x%016llX, 0x%016llX, 0x%016llX},\n", public_key2, private_key2, secret2);
29
+ }
30
+ }
@@ -0,0 +1,77 @@
1
+ using System;
2
+
3
+ namespace Funny.Crypto
4
+ {
5
+ public class DH64
6
+ {
7
+ private const ulong p = 0xffffffffffffffc5;
8
+ private const ulong g = 5;
9
+
10
+ private static ulong mul_mod_p(ulong a, ulong b) {
11
+ ulong m = 0;
12
+ while (b > 0) {
13
+ if ((b&1) > 0) {
14
+ var t = p - a;
15
+ if (m >= t) {
16
+ m -= t;
17
+ } else {
18
+ m += a;
19
+ }
20
+ }
21
+ if (a >= p-a) {
22
+ a = a*2 - p;
23
+ } else {
24
+ a = a * 2;
25
+ }
26
+ b >>= 1;
27
+ }
28
+ return m;
29
+ }
30
+
31
+ private static ulong pow_mod_p(ulong a, ulong b) {
32
+ if (b == 1) {
33
+ return a;
34
+ }
35
+ var t = pow_mod_p(a, b>>1);
36
+ t = mul_mod_p(t, t);
37
+ if ((b%2) > 0) {
38
+ t = mul_mod_p(t, a);
39
+ }
40
+ return t;
41
+ }
42
+
43
+ private static ulong powmodp(ulong a , ulong b) {
44
+ if (a == 0) {
45
+ throw new Exception("DH64 zero public key");
46
+ }
47
+ if (b == 0) {
48
+ throw new Exception("DH64 zero private key");
49
+ }
50
+ if (a > p) {
51
+ a %= p;
52
+ }
53
+ return pow_mod_p(a, b);
54
+ }
55
+
56
+ private Random rand;
57
+
58
+ public DH64() {
59
+ rand = new Random();
60
+ }
61
+
62
+ public void KeyPair(out ulong privateKey, out ulong publicKey) {
63
+ var a = (ulong)rand.Next();
64
+ var b = (ulong)rand.Next() + 1;
65
+ privateKey = (a<<32) | b;
66
+ publicKey = PublicKey(privateKey);
67
+ }
68
+
69
+ public ulong PublicKey(ulong privateKey) {
70
+ return powmodp(g, privateKey);
71
+ }
72
+
73
+ public ulong Secret(ulong privateKey, ulong anotherPublicKey) {
74
+ return powmodp(anotherPublicKey, privateKey);
75
+ }
76
+ }
77
+ }