v

Зеркало из https://github.com/vlang/v
Форк
0
/
ed25519.v 
181 строка · 4.9 Кб
1
module ed25519
2

3
import crypto.rand
4
import crypto.sha512
5
import crypto.internal.subtle
6
import crypto.ed25519.internal.edwards25519
7

8
// public_key_size is the sizeof public keys in bytes
9
pub const public_key_size = 32
10

11
// private_key_size is the sizeof private keys in bytes
12
pub const private_key_size = 64
13

14
// signature_size is the size of signatures generated and verified by this modules, in bytes.
15
pub const signature_size = 64
16

17
// seed_size is the size of private key seeds in bytes
18
pub const seed_size = 32
19

20
// `PublicKey` is Ed25519 public keys.
21
pub type PublicKey = []u8
22

23
// equal reports whether p and x have the same value.
24
pub fn (p PublicKey) equal(x []u8) bool {
25
	return subtle.constant_time_compare(p, PublicKey(x)) == 1
26
}
27

28
// PrivateKey is Ed25519 private keys
29
pub type PrivateKey = []u8
30

31
// seed returns the private key seed corresponding to priv.
32
// RFC 8032's private keys correspond to seeds in this module.
33
pub fn (priv PrivateKey) seed() []u8 {
34
	mut seed := []u8{len: seed_size}
35
	copy(mut seed, priv[..32])
36
	return seed
37
}
38

39
// public_key returns the []u8 corresponding to priv.
40
pub fn (priv PrivateKey) public_key() PublicKey {
41
	assert priv.len == private_key_size
42
	mut publickey := []u8{len: public_key_size}
43
	copy(mut publickey, priv[32..])
44
	return PublicKey(publickey)
45
}
46

47
// currentyly x not `crypto.PrivateKey`
48
pub fn (priv PrivateKey) equal(x []u8) bool {
49
	return subtle.constant_time_compare(priv, PrivateKey(x)) == 1
50
}
51

52
// sign signs the given message with priv.
53
pub fn (priv PrivateKey) sign(message []u8) ![]u8 {
54
	/*
55
	if opts.HashFunc() != crypto.Hash(0) {
56
		return nil, errors.New("ed25519: cannot sign hashed message")
57
	}*/
58

59
	return sign(priv, message)
60
}
61

62
// sign`signs the message with privatekey and returns a signature
63
pub fn sign(privatekey PrivateKey, message []u8) ![]u8 {
64
	mut signature := []u8{len: signature_size}
65
	sign_generic(mut signature, privatekey, message)!
66
	return signature
67
}
68

69
fn sign_generic(mut signature []u8, privatekey []u8, message []u8) ! {
70
	if privatekey.len != private_key_size {
71
		panic('ed25519: bad private key length: ${privatekey.len}')
72
	}
73
	seed, publickey := privatekey[..seed_size], privatekey[seed_size..]
74

75
	mut h := sha512.sum512(seed)
76
	mut s := edwards25519.new_scalar()
77
	s.set_bytes_with_clamping(h[..32])!
78
	mut prefix := unsafe { h[32..] }
79

80
	mut mh := sha512.new()
81
	mh.write(prefix)!
82
	mh.write(message)!
83

84
	mut msg_digest := []u8{cap: sha512.size}
85
	msg_digest = mh.sum(msg_digest)
86

87
	mut r := edwards25519.new_scalar()
88
	r.set_uniform_bytes(msg_digest)!
89

90
	mut rr := edwards25519.Point{}
91
	rr.scalar_base_mult(mut r)
92

93
	mut kh := sha512.new()
94
	kh.write(rr.bytes())!
95
	kh.write(publickey)!
96
	kh.write(message)!
97

98
	mut hram_digest := []u8{cap: sha512.size}
99
	hram_digest = kh.sum(hram_digest)
100
	mut k := edwards25519.new_scalar()
101
	k.set_uniform_bytes(hram_digest)!
102

103
	mut ss := edwards25519.new_scalar()
104
	ss.multiply_add(k, s, r)
105

106
	copy(mut signature[..32], rr.bytes())
107
	copy(mut signature[32..], ss.bytes())
108
}
109

110
// verify reports whether sig is a valid signature of message by publickey.
111
pub fn verify(publickey PublicKey, message []u8, sig []u8) !bool {
112
	if publickey.len != public_key_size {
113
		return error('ed25519: bad public key length: ${publickey.len}')
114
	}
115

116
	if sig.len != signature_size || sig[63] & 224 != 0 {
117
		return false
118
	}
119

120
	mut aa := edwards25519.Point{}
121
	aa.set_bytes(publickey)!
122

123
	mut kh := sha512.new()
124
	kh.write(sig[..32])!
125
	kh.write(publickey)!
126
	kh.write(message)!
127

128
	mut hram_digest := []u8{cap: sha512.size}
129
	hram_digest = kh.sum(hram_digest)
130

131
	mut k := edwards25519.new_scalar()
132
	k.set_uniform_bytes(hram_digest)!
133

134
	mut ss := edwards25519.new_scalar()
135
	ss.set_canonical_bytes(sig[32..])!
136

137
	// [S]B = R + [k]A --> [k](-A) + [S]B = R
138
	mut minus_a := edwards25519.Point{}
139
	minus_a.negate(aa)
140
	mut rr := edwards25519.Point{}
141
	rr.vartime_double_scalar_base_mult(k, minus_a, ss)
142

143
	return subtle.constant_time_compare(sig[..32], rr.bytes()) == 1
144
}
145

146
// generate_key generates a public/private key pair entropy using `crypto.rand`.
147
pub fn generate_key() !(PublicKey, PrivateKey) {
148
	mut seed := rand.bytes(seed_size)!
149

150
	privatekey := new_key_from_seed(seed)
151
	mut publickey := []u8{len: public_key_size}
152
	copy(mut publickey, privatekey[32..])
153

154
	return publickey, privatekey
155
}
156

157
// new_key_from_seed calculates a private key from a seed. private keys of RFC 8032
158
// correspond to seeds in this module
159
pub fn new_key_from_seed(seed []u8) PrivateKey {
160
	// Outline the function body so that the returned key can be stack-allocated.
161
	mut privatekey := []u8{len: private_key_size}
162
	new_key_from_seed_generic(mut privatekey, seed)
163
	return PrivateKey(privatekey)
164
}
165

166
fn new_key_from_seed_generic(mut privatekey []u8, seed []u8) {
167
	if seed.len != seed_size {
168
		panic('ed25519: bad seed length: ${seed.len}')
169
	}
170

171
	mut h := sha512.sum512(seed)
172
	mut s := edwards25519.new_scalar()
173
	s.set_bytes_with_clamping(h[..32]) or { panic(err) }
174
	mut aa := edwards25519.Point{}
175
	aa.scalar_base_mult(mut s)
176

177
	mut publickey := aa.bytes()
178

179
	copy(mut privatekey, seed)
180
	copy(mut privatekey[32..], publickey)
181
}
182

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.