├── .gitignore ├── LICENSE ├── README.md ├── axlsign └── axlsign.go └── test └── test.go /.gitignore: -------------------------------------------------------------------------------- 1 | update.bat 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Axlsign 2 | ======= 3 | 4 | Ed25519-like signatures with X25519 keys, Axolotl-style. 5 | 6 | ## Functions 7 | 8 | Functions accept and return `[]uint8 Array`s. 9 | 10 | ### generateKeyPair(seed) -> keyPair 11 | 12 | Generates a new key pair from the given 32-byte secret seed (which should be 13 | generated with a CSPRNG) and returns it as object: 14 | 15 | ``` 16 | keyPair = { 17 | privateKey: IntArray // 32-byte private key 18 | publicKey: IntArray // 32-byte public key 19 | } 20 | ``` 21 | 22 | The returned keys can be used for signing and key agreement. 23 | 24 | ### sign(privateKey, message, [random]) -> signature 25 | 26 | Signs the given message using the private key and returns signature. 27 | 28 | Optional random data argument (which must have 64 random bytes) turns on 29 | hash separation and randomization to make signatures non-deterministic. 30 | 31 | ### verify(publicKey, message, signature) -> 1 | 0 32 | 33 | Verifies the given signature for the message using the given private key. 34 | Returns `1` if the signature is valid, `0` otherwise. 35 | 36 | ### signMessage(privateKey, message, [random]) -> signedMessage 37 | 38 | Signs the given message using the private key and returns 39 | a signed message (signature concatenated with the message copy). 40 | 41 | Optional random data argument (which must have 64 random bytes) turns on 42 | hash separation and randomization to make signatures non-deterministic. 43 | 44 | ### openMessage(publicKey, signedMessage) -> message | null 45 | 46 | Verifies signed message with the public key and returns the original message 47 | without signature if it's correct or `nil` if verification fails. 48 | 49 | ### sharedKey(privateKey, publicKey) -> rawSharedKey 50 | 51 | Returns a raw shared key between own private key and peer's public key (in 52 | other words, this is an ECC Diffie-Hellman function X25519, performing 53 | scalar multiplication). 54 | 55 | ## Credits 56 | 57 | Ported to Go (https://golang.org/) by Miguel Lucero nov 2017. 58 | You can use it under MIT or CC0 license. 59 | 60 | Curve25519 signatures idea and math by Trevor Perrin 61 | 62 | 63 | Derived from axlsign.js written by Dmitry Chestnykh. 64 | 65 | -------------------------------------------------------------------------------- /axlsign/axlsign.go: -------------------------------------------------------------------------------- 1 | // Curve25519 signatures (and also key agreement) 2 | // like in the early Axolotl. 3 | // 4 | // Ported to Go by Miguel Sandro Lucero. miguel.sandro@gmail.com. 2017.11.03 5 | // You can use it under MIT or CC0 license. 6 | // 7 | // Curve25519 signatures idea and math by Trevor Perrin 8 | // https://moderncrypto.org/mail-archive/curves/2014/000205.html 9 | // 10 | // Derived from axlsign.js written by Dmitry Chestnykh. https://github.com/wavesplatform/curve25519-js 11 | 12 | package axlsign 13 | 14 | import "math" 15 | 16 | func gf(params ...[]int64) []int64 { 17 | r := make([]int64, 16) 18 | if len(params) > 0 { 19 | for i := 0; i < len(params[0]); i++ { 20 | r[i] = params[0][i] 21 | } 22 | } 23 | return r 24 | } 25 | 26 | var _0 = make([]uint8, 16) 27 | 28 | var _9 = []uint8 { 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 29 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 30 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 31 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} 32 | 33 | var gf0 = gf() 34 | 35 | var gf1 = gf( []int64 {1} ) 36 | 37 | var _121665 = gf( []int64 {0xdb41, 1} ) 38 | 39 | var D = gf( []int64 {0x78a3, 0x1359, 0x4dca, 0x75eb, 40 | 0xd8ab, 0x4141, 0x0a4d, 0x0070, 41 | 0xe898, 0x7779, 0x4079, 0x8cc7, 42 | 0xfe73, 0x2b6f, 0x6cee, 0x5203} ) 43 | 44 | var D2 = gf( []int64 {0xf159, 0x26b2, 0x9b94, 0xebd6, 45 | 0xb156, 0x8283, 0x149a, 0x00e0, 46 | 0xd130, 0xeef3, 0x80f2, 0x198e, 47 | 0xfce7, 0x56df, 0xd9dc, 0x2406} ) 48 | 49 | var X = gf( []int64 {0xd51a, 0x8f25, 0x2d60, 0xc956, 50 | 0xa7b2, 0x9525, 0xc760, 0x692c, 51 | 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 52 | 0x53fe, 0xcd6e, 0x36d3, 0x2169} ) 53 | 54 | var Y = gf( []int64 {0x6658, 0x6666, 0x6666, 0x6666, 55 | 0x6666, 0x6666, 0x6666, 0x6666, 56 | 0x6666, 0x6666, 0x6666, 0x6666, 57 | 0x6666, 0x6666, 0x6666, 0x6666} ) 58 | 59 | var I = gf( []int64 {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 60 | 0xe478, 0xad2f, 0x1806, 0x2f43, 61 | 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 62 | 0xdf0b, 0x4fc1, 0x2480, 0x2b83} ) 63 | 64 | func ushr(v int) int { 65 | return int( uint32( v ) ) 66 | } 67 | 68 | func ts64(x []uint8 , i int, h int, l int) { 69 | x[i] = uint8( (h >> 24) & 0xff ) 70 | x[i+1] = uint8( (h >> 16) & 0xff ) 71 | x[i+2] = uint8( (h >> 8) & 0xff ) 72 | x[i+3] = uint8( h & 0xff ) 73 | x[i+4] = uint8( (l >> 24) & 0xff ) 74 | x[i+5] = uint8( (l >> 16) & 0xff ) 75 | x[i+6] = uint8 ( (l >> 8) & 0xff ) 76 | x[i+7] = uint8( l & 0xff ) 77 | } 78 | 79 | func vn(x []uint8, xi int, y []uint8, yi int, n int) int { 80 | var d uint8 = 0 81 | for i := 0; i < n; i++ { 82 | d = d | ( x[xi+i] ^ y[yi+i] ) 83 | } 84 | return int( (1 & ( ushr( int(d) - 1 ) >> 8 ) ) - 1 ) 85 | } 86 | 87 | func crypto_verify_32(x []uint8, xi int, y []uint8, yi int) int { 88 | return vn(x,xi,y,yi,32) 89 | } 90 | 91 | func set25519(r []int64, a []int64) { 92 | for i := 0; i < 16; i++ { 93 | r[i] = a[i] | 0 94 | } 95 | } 96 | 97 | func car25519(o []int64) { 98 | var v int64 99 | var c = 1 100 | for i := 0; i < 16; i++ { 101 | v = o[i] + int64(c + 65535) 102 | c = int( math.Floor( float64(v) / 65536.0) ) 103 | o[i] = v - int64(c * 65536) 104 | } 105 | o[0] += int64( c-1 + 37 * (c-1) ) 106 | } 107 | 108 | func sel25519(p []int64, q []int64, b int) { 109 | var t int64 110 | var c = int64( ^(b-1) ) 111 | for i := 0; i < 16; i++ { 112 | t = c & ( p[i] ^ q[i] ) 113 | p[i] = p[i] ^ t 114 | q[i] = q[i] ^ t 115 | } 116 | } 117 | 118 | func pack25519(o []uint8, n []int64) { 119 | var b int64 120 | var m = gf() 121 | var t = gf() 122 | 123 | for i := 0; i < 16; i++ { 124 | t[i] = n[i] 125 | } 126 | car25519(t) 127 | car25519(t) 128 | car25519(t) 129 | 130 | for c := 0; c < 2; c++ { 131 | m[0] = t[0] - 0xffed 132 | for i := 1; i < 15; i++ { 133 | m[i] = t[i] - 0xffff - ((m[i-1] >> 16) & 1) 134 | m[i-1] = m[i-1] & 0xffff 135 | } 136 | m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1) 137 | b = (m[15] >> 16) & 1 138 | m[14] = m[14] & 0xffff 139 | sel25519(t, m, int(1-b) ) 140 | } 141 | 142 | for i := 0; i < 16; i++ { 143 | o[2*i] = uint8(t[i] & 0xff ) 144 | o[2*i+1] = uint8(t[i] >> 8 ) 145 | } 146 | } 147 | 148 | func neq25519(a []int64, b []int64) int { 149 | var c = make([]uint8, 32) 150 | var d = make([]uint8, 32) 151 | pack25519(c, a) 152 | pack25519(d, b) 153 | return crypto_verify_32(c, 0, d, 0) 154 | } 155 | 156 | func par25519(a []int64) int { 157 | var d = make([]uint8, 32) 158 | pack25519(d, a) 159 | return int(d[0]) & 1 160 | } 161 | 162 | func unpack25519(o []int64, n []uint8) { 163 | for i := 0; i < 16; i++ { 164 | o[i] = int64(n[2*i]) + ( int64(n[2*i+1]) << 8) 165 | } 166 | o[15] = o[15] & 0x7fff 167 | } 168 | 169 | func A(o []int64, a []int64, b []int64) { 170 | for i := 0; i < 16; i++ { 171 | o[i] = a[i] + b[i] 172 | } 173 | } 174 | 175 | func Z(o []int64, a []int64, b []int64) { 176 | for i := 0; i < 16; i++ { 177 | o[i] = a[i] - b[i] 178 | } 179 | } 180 | 181 | // optimized by Miguel 182 | func M(o []int64, a []int64, b []int64) { 183 | var at = make([]int64, 32) 184 | var ab = make([]int64, 16) 185 | 186 | for i := 0; i < 16; i++ { 187 | ab[i] = b[i] 188 | } 189 | 190 | var v int64 191 | for i := 0; i < 16; i++ { 192 | v = a[i] 193 | for j := 0; j < 16; j++ { 194 | at[j+i] += v * ab[j] 195 | } 196 | } 197 | 198 | for i := 0; i < 15; i++ { 199 | at[i] += 38 * at[i+16] 200 | } 201 | // t15 left as is 202 | 203 | // first car 204 | var c int64 = 1 205 | for i := 0; i < 16; i++ { 206 | v = at[i] + c + 65535 207 | c = int64( math.Floor(float64(v) / 65536.0) ) 208 | at[i] = v - c * 65536 209 | } 210 | at[0] += c-1 + 37 * (c-1) 211 | 212 | // second car 213 | c = 1 214 | for i := 0; i < 16; i++ { 215 | v = at[i] + c + 65535 216 | c = int64( math.Floor(float64(v) / 65536.0) ) 217 | at[i] = v - c * 65536 218 | } 219 | at[0] += c-1 + 37 * (c-1) 220 | 221 | for i := 0; i < 16; i++ { 222 | o[i] = at[i] 223 | } 224 | 225 | } 226 | 227 | func S(o []int64, a []int64) { 228 | M(o, a, a) 229 | } 230 | 231 | func inv25519(o []int64, i []int64) { 232 | var c = gf() 233 | for a := 0; a < 16; a++ { 234 | c[a] = i[a] 235 | } 236 | 237 | for a := 253; a >= 0; a-- { 238 | S(c, c) 239 | if(a != 2 && a != 4) { 240 | M(c, c, i) 241 | } 242 | } 243 | for a := 0; a < 16; a++ { 244 | o[a] = c[a] 245 | } 246 | } 247 | 248 | func pow2523(o []int64, i []int64) { 249 | var c = gf() 250 | for a := 0; a < 16; a++ { 251 | c[a] = i[a] 252 | } 253 | for a := 250; a >= 0; a-- { 254 | S(c, c) 255 | if(a != 1) { 256 | M(c, c, i) 257 | } 258 | } 259 | for a := 0; a < 16; a++ { 260 | o[a] = c[a] 261 | } 262 | } 263 | 264 | func crypto_scalarmult(q []uint8, n []uint8, p []uint8) int { 265 | var z = make([]uint8, 32) 266 | var x = make([]int64, 80) 267 | var r int 268 | 269 | var a = gf() 270 | var b = gf() 271 | var c = gf() 272 | var d = gf() 273 | var e = gf() 274 | var f = gf() 275 | 276 | for i := 0; i < 31; i++ { 277 | z[i] = n[i] 278 | } 279 | z[31] = (n[31] & 127) | 64 280 | z[0] = z[0] & 248 281 | 282 | unpack25519(x,p) 283 | 284 | for i := 0; i < 16; i++ { 285 | b[i] = x[i] 286 | d[i] = 0 287 | a[i] = 0 288 | c[i] = 0 289 | } 290 | a[0] = 1 291 | d[0] = 1 292 | 293 | for i := 254; i >= 0; i-- { 294 | r = int( ( ( z[i >> uint(3) ] ) >> uint(i & 7) ) & 1 ) 295 | 296 | sel25519(a,b,r) 297 | sel25519(c,d,r) 298 | 299 | A(e,a,c) 300 | Z(a,a,c) 301 | A(c,b,d) 302 | Z(b,b,d) 303 | S(d,e) 304 | S(f,a) 305 | M(a,c,a) 306 | M(c,b,e) 307 | A(e,a,c) 308 | Z(a,a,c) 309 | S(b,a) 310 | Z(c,d,f) 311 | 312 | M(a,c,_121665) 313 | A(a,a,d) 314 | M(c,c,a) 315 | M(a,d,f) 316 | M(d,b,x) 317 | S(b,e) 318 | 319 | sel25519(a,b,r) 320 | sel25519(c,d,r) 321 | 322 | } 323 | 324 | for i :=0; i<16; i++ { 325 | x[i+16]=a[i] 326 | x[i+32]=c[i] 327 | x[i+48]=b[i] 328 | x[i+64]=d[i] 329 | } 330 | 331 | var x32 = x[32:] 332 | var x16 = x[16:] 333 | 334 | inv25519(x32,x32) 335 | 336 | M(x16,x16,x32) 337 | 338 | pack25519(q,x16) 339 | 340 | return 0 341 | } 342 | 343 | func crypto_scalarmult_base(q []uint8, n []uint8) int { 344 | return crypto_scalarmult(q, n, _9) 345 | } 346 | 347 | // Constantes de cada ronda del SHA-512 348 | var K = []int64 { 349 | 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, 350 | 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, 351 | 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, 352 | 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, 353 | 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, 354 | 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, 355 | 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, 356 | 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, 357 | 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, 358 | 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, 359 | 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, 360 | 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, 361 | 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, 362 | 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, 363 | 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, 364 | 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, 365 | 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, 366 | 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, 367 | 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, 368 | 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, 369 | 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, 370 | 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, 371 | 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, 372 | 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, 373 | 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, 374 | 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, 375 | 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, 376 | 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, 377 | 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, 378 | 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, 379 | 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, 380 | 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, 381 | 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, 382 | 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, 383 | 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, 384 | 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, 385 | 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, 386 | 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, 387 | 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, 388 | 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817} 389 | 390 | // optimized by miguel 391 | func crypto_hashblocks_hl(hh []int, hl []int, m []uint8, _n int) int { 392 | 393 | var wh = make([]int, 16) 394 | var wl = make([]int, 16) 395 | 396 | var bh = make([]int, 8) 397 | var bl = make([]int, 8) 398 | 399 | var th int 400 | var tl int 401 | var h int 402 | var l int 403 | var a int 404 | var b int 405 | var c int 406 | var d int 407 | 408 | var ah = make([]int, 8) 409 | var al = make([]int, 8) 410 | for i := 0; i<8; i++ { 411 | ah[i] = hh[i] 412 | al[i] = hl[i] 413 | } 414 | 415 | var pos = 0 416 | var n = _n 417 | for n >= 128 { 418 | 419 | for i := 0; i < 16; i++ { 420 | var j = 8 * i + pos 421 | wh[i] = (int(m[j+0]) << 24) | (int(m[j+1]) << 16) | (int(m[j+2]) << 8) | int(m[j+3]) 422 | wl[i] = (int(m[j+4]) << 24) | (int(m[j+5]) << 16) | (int(m[j+6]) << 8) | int(m[j+7]) 423 | } 424 | 425 | for i := 0; i < 80; i++ { 426 | for j := 0; j<7; j++ { 427 | bh[j] = ah[j] 428 | bl[j] = al[j] 429 | } 430 | 431 | // add 432 | h = ah[7] 433 | l = al[7] 434 | 435 | a = l & 0xffff; b = ushr(l) >> 16 436 | c = h & 0xffff; d = ushr(h) >> 16 437 | 438 | // Sigma1 439 | h = (( ushr(ah[4]) >> 14) | (al[4] << (32-14))) ^ (( ushr(ah[4]) >> 18) | (al[4] << (32-18))) ^ (( ushr(al[4]) >> (41-32)) | (ah[4] << (32-(41-32)))) 440 | l = (( ushr(al[4]) >> 14) | (ah[4] << (32-14))) ^ (( ushr(al[4]) >> 18) | (ah[4] << (32-18))) ^ (( ushr(ah[4]) >> (41-32)) | (al[4] << (32-(41-32)))) 441 | 442 | a += l & 0xffff 443 | b += ushr(l) >> 16 444 | c += h & 0xffff 445 | d += ushr(h) >> 16 446 | 447 | // Ch 448 | h = (ah[4] & ah[5]) ^ (^ah[4] & ah[6]) 449 | l = (al[4] & al[5]) ^ (^al[4] & al[6]) 450 | 451 | a += l & 0xffff; b += ushr(l) >> 16 452 | c += h & 0xffff; d += ushr(h) >> 16 453 | 454 | // K 455 | h = int( int32( K[i*2] ) ) 456 | l = int( int32( K[i*2+1] ) ) 457 | 458 | a += l & 0xffff 459 | b += ushr(l) >> 16 460 | c += h & 0xffff 461 | d += ushr(h) >> 16 462 | 463 | // w 464 | h = wh[i%16] 465 | l = wl[i%16] 466 | 467 | a += l & 0xffff 468 | b += ushr(l) >> 16 469 | c += h & 0xffff 470 | d += ushr(h) >> 16 471 | 472 | b += ushr(a) >> 16 473 | c += ushr(b) >> 16 474 | d += ushr(c) >> 16 475 | 476 | // *** R 477 | // th = c & 0xffff | ( d << 16 ) 478 | // tl = a & 0xffff | ( b << 16 ) 479 | th = c & 0xffff | d << 16 480 | tl = a & 0xffff | b << 16 481 | 482 | // add 483 | h = th 484 | l = tl 485 | 486 | a = l & 0xffff 487 | b = ushr(l) >> 16 488 | c = h & 0xffff 489 | d = ushr(h) >> 16 490 | 491 | // Sigma0 492 | h = (( ushr(ah[0]) >> 28) | (al[0] << (32-28))) ^ (( ushr(al[0]) >> (34-32)) | (ah[0] << (32-(34-32)))) ^ (( ushr(al[0]) >> (39-32)) | (ah[0] << (32-(39-32)))) 493 | l = (( ushr(al[0]) >> 28) | (ah[0] << (32-28))) ^ (( ushr(ah[0]) >> (34-32)) | (al[0] << (32-(34-32)))) ^ (( ushr(ah[0]) >> (39-32)) | (al[0] << (32-(39-32)))) 494 | 495 | a += l & 0xffff 496 | b += ushr(l) >> 16 497 | c += h & 0xffff 498 | d += ushr(h) >> 16 499 | 500 | // Maj 501 | h = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2]) 502 | l = (al[0] & al[1]) ^ (al[0] & al[2]) ^ (al[1] & al[2]) 503 | 504 | a += l & 0xffff; b += ushr(l) >> 16 505 | c += h & 0xffff; d += ushr(h) >> 16 506 | 507 | b += ushr(a) >> 16 508 | c += ushr(b) >> 16 509 | d += ushr(c) >> 16 510 | 511 | bh[7] = (c & 0xffff) | (d << 16) 512 | bl[7] = (a & 0xffff) | (b << 16) 513 | 514 | // add 515 | h = bh[3] 516 | l = bl[3] 517 | 518 | a = l & 0xffff 519 | b = ushr(l) >> 16 520 | c = h & 0xffff 521 | d = ushr(h) >> 16 522 | 523 | h = th 524 | l = tl 525 | 526 | a += l & 0xffff 527 | b += ushr(l) >> 16 528 | c += h & 0xffff 529 | d += ushr(h) >> 16 530 | 531 | b += ushr(a) >> 16 532 | c += ushr(b) >> 16 533 | d += ushr(c) >> 16 534 | 535 | bh[3] = (c & 0xffff) | (d << 16) 536 | bl[3] = (a & 0xffff) | (b << 16) 537 | 538 | for j := 0; j<8; j++ { 539 | var k = ( j + 1 ) % 8 540 | ah[k] = bh[j] 541 | al[k] = bl[j] 542 | } 543 | 544 | if (i % 16 == 15) { 545 | for j := 0; j<16; j++ { 546 | // add 547 | h = wh[j] 548 | l = wl[j] 549 | 550 | a = l & 0xffff; b = ushr(l) >> 16 551 | c = h & 0xffff; d = ushr(h) >> 16 552 | 553 | h = wh[(j+9)%16] 554 | l = wl[(j+9)%16] 555 | 556 | a += l & 0xffff; b += ushr(l) >> 16 557 | c += h & 0xffff; d += ushr(h) >> 16 558 | 559 | // sigma0 560 | th = wh[(j+1)%16] 561 | tl = wl[(j+1)%16] 562 | 563 | h = (( ushr(th) >> 1) | (tl << (32-1))) ^ (( ushr(th) >> 8) | (tl << (32-8))) ^ ( ushr(th) >> 7) 564 | l = (( ushr(tl) >> 1) | (th << (32-1))) ^ (( ushr(tl) >> 8) | (th << (32-8))) ^ (( ushr(tl) >> 7) | (th << (32-7))) 565 | 566 | a += l & 0xffff; b += ushr(l) >> 16 567 | c += h & 0xffff; d += ushr(h) >> 16 568 | 569 | // sigma1 570 | th = wh[(j+14)%16] 571 | tl = wl[(j+14)%16] 572 | 573 | h = (( ushr(th) >> 19) | (tl << (32-19))) ^ (( ushr(tl) >> (61-32)) | (th << (32-(61-32)))) ^ ( ushr(th) >> 6) 574 | l = (( ushr(tl) >> 19) | (th << (32-19))) ^ (( ushr(th) >> (61-32)) | (tl << (32-(61-32)))) ^ (( ushr(tl) >> 6) | (th << (32-6))) 575 | 576 | a += l & 0xffff; b += ushr(l) >> 16 577 | c += h & 0xffff; d += ushr(h) >> 16 578 | 579 | b += ushr(a) >> 16 580 | c += ushr(b) >> 16 581 | d += ushr(c) >> 16 582 | 583 | wh[j] = ( (c & 0xffff) | (d << 16) ) 584 | wl[j] = ( (a & 0xffff) | (b << 16) ) 585 | } 586 | } 587 | } 588 | 589 | // add 590 | a = 0; b = 0; c = 0; d = 0 591 | for k := 0; k<8; k++ { 592 | if( k == 0 ) { 593 | h = ah[0] 594 | l = al[0] 595 | a = l & 0xffff; b = ushr(l) >> 16 596 | c = h & 0xffff; d = ushr(h) >> 16 597 | } 598 | 599 | h = hh[k] 600 | l = hl[k] 601 | 602 | a += l & 0xffff; b += ushr(l) >> 16 603 | c += h & 0xffff; d += ushr(h) >> 16 604 | 605 | b += ushr(a) >> 16 606 | c += ushr(b) >> 16 607 | d += ushr(c) >> 16 608 | 609 | hh[k] = (c & 0xffff) | (d << 16) 610 | ah[k] = (c & 0xffff) | (d << 16) 611 | 612 | hl[k] = (a & 0xffff) | (b << 16) 613 | al[k] = (a & 0xffff) | (b << 16) 614 | 615 | if( k < 7 ) { 616 | h = ah[k+1] 617 | l = al[k+1] 618 | 619 | a = l & 0xffff; b = ushr(l) >> 16 620 | c = h & 0xffff; d = ushr(h) >> 16 621 | } 622 | } 623 | 624 | pos += 128 625 | n -= 128 626 | } 627 | 628 | return n 629 | } 630 | 631 | var _HH = []int64 {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19} 632 | var _HL = []int64 {0xf3bcc908, 0x84caa73b, 0xfe94f82b, 0x5f1d36f1, 0xade682d1, 0x2b3e6c1f, 0xfb41bd6b, 0x137e2179} 633 | 634 | func toIntArray(o []int64) []int { 635 | var v = make([]int, len(o)) 636 | for i := 0; i < len(o); i++ { 637 | v[i] = int(int32( o[i] ) ) 638 | // v[i] = int( o[i] ) 639 | } 640 | return v 641 | } 642 | 643 | func crypto_hash(out []uint8, m []uint8, _n int) int { 644 | var hh = toIntArray( _HH ) 645 | var hl = toIntArray( _HL ) 646 | var x = make([]uint8, 256) 647 | var n = _n 648 | var b = n 649 | 650 | crypto_hashblocks_hl(hh, hl, m, n) 651 | 652 | n %= 128 653 | 654 | for i := 0; i= 0; i-- { 741 | b = int( s[(i/8)|0] >> uint8( i & 7 ) ) & 1; 742 | cswap(p, q, b) 743 | add(q, p) 744 | add(p, p) 745 | cswap(p, q, b) 746 | } 747 | } 748 | 749 | func scalarbase(p [][]int64, s []uint8) { 750 | var q = [][]int64 {gf(), gf(), gf(), gf()} 751 | set25519(q[0], X) 752 | set25519(q[1], Y) 753 | set25519(q[2], gf1) 754 | M(q[3], X, Y) 755 | scalarmult(p, q, s) 756 | } 757 | 758 | var L = []int64 { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 759 | 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 760 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10 } 761 | 762 | func modL(r []uint8, x []int64) { 763 | 764 | var carry int64 765 | 766 | for i := 63; i >= 32; i-- { 767 | carry = 0 768 | var j = i - 32 769 | var k = i - 12 770 | for j < k { 771 | x[j] += carry - 16 * x[i] * L[j - (i - 32)] 772 | carry = (x[j] + 128) >> 8 773 | x[j] -= carry * 256 774 | j += 1 775 | } 776 | x[j] += carry 777 | x[i] = 0 778 | } 779 | 780 | carry = 0 781 | for j := 0; j<32; j++ { 782 | x[j] += carry - (x[31] >> 4) * L[j] 783 | carry = x[j] >> 8 784 | x[j] = x[j] & 255 785 | } 786 | 787 | for j := 0; j<32; j++ { 788 | x[j] -= carry * L[j] 789 | } 790 | 791 | for i := 0; i < 32; i++ { 792 | x[i+1] += x[i] >> 8 793 | r[i] = uint8( x[i] & 255 ) 794 | } 795 | 796 | } 797 | 798 | func reduce(r []uint8) { 799 | var x = make([]int64, 64) 800 | for i := 0; i < 64; i++ { 801 | x[i] = int64( r[i] ) 802 | } 803 | for i := 0; i < 64; i++ { 804 | r[i] = 0 805 | } 806 | modL(r, x) 807 | } 808 | 809 | // Like crypto_sign, but uses secret key directly in hash. 810 | func crypto_sign_direct(sm []uint8, m []uint8, n int, sk []uint8) int { 811 | var h = make([]uint8, 64) 812 | var r = make([]uint8, 64) 813 | var x = make([]int64, 64) 814 | var p = [][]int64 {gf(), gf(), gf(), gf()} 815 | 816 | for i := 0; i < n; i++ { 817 | sm[64 + i] = m[i] 818 | } 819 | 820 | for i := 0; i < 32; i++ { 821 | sm[32 + i] = sk[i] 822 | } 823 | 824 | crypto_hash(r, sm[32:], n+32) 825 | 826 | reduce(r) 827 | 828 | scalarbase(p, r) 829 | 830 | pack(sm, p) 831 | 832 | for i := 0; i < 32; i++ { 833 | sm[i + 32] = sk[32 + i] 834 | } 835 | 836 | crypto_hash(h, sm, n + 64) 837 | reduce(h) 838 | 839 | for i := 0; i < 64; i++ { 840 | x[i] = 0 841 | } 842 | 843 | for i := 0; i < 32; i++ { 844 | x[i] = int64(r[i]) 845 | } 846 | 847 | for i := 0; i < 32; i++ { 848 | for j :=0; j<32; j++ { 849 | x[i+j] += int64( h[i] ) * int64( sk[j] ) 850 | } 851 | } 852 | 853 | var tmp = sm[32:] 854 | modL(tmp, x) 855 | for i := 0; i < len(tmp); i++ { 856 | sm[32+i] = tmp[i] 857 | } 858 | 859 | return n + 64 860 | 861 | } 862 | 863 | // Note: sm must be n+128. 864 | func crypto_sign_direct_rnd(sm []uint8, m []uint8, n int, sk []uint8, rnd []uint8) int { 865 | var h = make([]uint8, 64) 866 | var r = make([]uint8, 64) 867 | var x = make([]int64, 64) 868 | var p = [][]int64 {gf(), gf(), gf(), gf()} 869 | 870 | // Hash separation. 871 | sm[0] = 0xfe 872 | for i := 1; i < 32; i++ { 873 | sm[i] = 0xff 874 | } 875 | 876 | // Secret key. 877 | for i := 0; i < 32; i++ { 878 | sm[32 + i] = sk[i] 879 | } 880 | 881 | // Message. 882 | for i := 0; i < n; i++ { 883 | sm[64 + i] = m[i] 884 | } 885 | 886 | // Random suffix. 887 | for i := 0; i < 64; i++ { 888 | sm[n + 64 + i] = rnd[i] 889 | } 890 | 891 | crypto_hash(r, sm, n+128) 892 | 893 | reduce(r) 894 | scalarbase(p, r) 895 | pack(sm, p) 896 | 897 | for i := 0; i < 32; i++ { 898 | sm[i + 32] = sk[32 + i] 899 | } 900 | 901 | crypto_hash(h, sm, n + 64) 902 | reduce(h) 903 | 904 | // Wipe out random suffix. 905 | for i := 0; i < 64; i++ { 906 | sm[n + 64 + i] = 0 907 | } 908 | 909 | for i := 0; i < 64; i++ { 910 | x[i] = 0 911 | } 912 | 913 | for i := 0; i < 32; i++ { 914 | x[i] = int64( r[i] ) 915 | } 916 | 917 | for i := 0; i < 32; i++ { 918 | for j := 0; j<32; j++ { 919 | x[i+j] += int64( h[i] ) * int64( sk[j] ) 920 | } 921 | } 922 | 923 | var tmp = sm[32:] 924 | modL(tmp, x) 925 | for i := 0; i < len(tmp); i++ { 926 | sm[32+i] = tmp[i] 927 | } 928 | 929 | return n + 64 930 | } 931 | 932 | func curve25519_sign(sm []uint8, m []uint8, n int, sk []uint8, opt_rnd []uint8) int { 933 | // If opt_rnd is provided, sm must have n + 128, 934 | // otherwise it must have n + 64 bytes. 935 | 936 | // Convert Curve25519 secret key into Ed25519 secret key (includes pub key). 937 | var edsk = make([]uint8, 64) 938 | var p = [][]int64 {gf(), gf(), gf(), gf()} 939 | 940 | for i := 0; i < 32; i++ { 941 | edsk[i] = sk[i] 942 | } 943 | 944 | // Ensure key is in the correct format. 945 | edsk[0] = edsk[0] & 248 946 | edsk[31] = edsk[31] & 127 947 | edsk[31] = edsk[31] | 64 948 | 949 | scalarbase(p, edsk) 950 | 951 | var tmp = edsk[32:] 952 | pack(tmp, p) 953 | for i := 0; i < len(tmp); i++ { 954 | edsk[32+i] = tmp[i] 955 | } 956 | 957 | // Remember sign bit. 958 | var signBit = edsk[63] & 128 959 | var smlen int 960 | 961 | if (opt_rnd == nil ) { 962 | smlen = crypto_sign_direct(sm, m, n, edsk) 963 | } else { 964 | smlen = crypto_sign_direct_rnd(sm, m, n, edsk, opt_rnd) 965 | } 966 | 967 | // Copy sign bit from public key into signature. 968 | sm[63] = sm[63] | signBit 969 | 970 | return smlen 971 | } 972 | 973 | func unpackneg(r [][]int64, p []uint8) int { 974 | var t = gf() 975 | var chk = gf() 976 | var num = gf() 977 | var den = gf() 978 | var den2 = gf() 979 | var den4 = gf() 980 | var den6 = gf() 981 | 982 | set25519(r[2], gf1) 983 | unpack25519(r[1], p) 984 | 985 | S(num, r[1]) 986 | M(den, num, D) 987 | Z(num, num, r[2]) 988 | A(den, r[2], den) 989 | 990 | S(den2, den) 991 | S(den4, den2) 992 | M(den6, den4, den2) 993 | M(t, den6, num) 994 | M(t, t, den) 995 | 996 | pow2523(t, t) 997 | M(t, t, num) 998 | M(t, t, den) 999 | M(t, t, den) 1000 | M(r[0], t, den) 1001 | 1002 | S(chk, r[0]) 1003 | M(chk, chk, den) 1004 | 1005 | if ( neq25519(chk, num) != 0 ) { 1006 | M(r[0], r[0], I) 1007 | } 1008 | 1009 | S(chk, r[0]) 1010 | M(chk, chk, den) 1011 | 1012 | if ( neq25519(chk, num) != 0 ) { 1013 | return -1 1014 | } 1015 | 1016 | if ( par25519(r[0]) == (int(p[31]) >> 7) ) { 1017 | Z(r[0], gf0, r[0]) 1018 | } 1019 | 1020 | M(r[3], r[0], r[1]) 1021 | 1022 | return 0 1023 | } 1024 | 1025 | func crypto_sign_open(m []uint8, sm []uint8, _n int, pk []uint8) int { 1026 | var t = make([]uint8, 32) 1027 | var h = make([]uint8, 64) 1028 | var p = [][]int64 {gf(), gf(), gf(), gf()} 1029 | var q = [][]int64 {gf(), gf(), gf(), gf()} 1030 | var n = _n 1031 | 1032 | var mlen = -1 1033 | if (n < 64) { 1034 | return mlen 1035 | } 1036 | 1037 | if ( unpackneg(q, pk) != 0 ) { 1038 | return mlen 1039 | } 1040 | 1041 | for i := 0; i < n; i++ { 1042 | m[i] = sm[i] 1043 | } 1044 | 1045 | for i := 0; i < 32; i++ { 1046 | m[i+32] = pk[i] 1047 | } 1048 | 1049 | crypto_hash(h, m, n) 1050 | 1051 | reduce(h) 1052 | scalarmult(p, q, h) 1053 | 1054 | scalarbase(q, sm[32:]); 1055 | add(p, q) 1056 | pack(t, p) 1057 | 1058 | n -= 64 1059 | if ( crypto_verify_32(sm, 0, t, 0) != 0 ) { 1060 | for i := 0; i < n; i++ { 1061 | m[i] = 0 1062 | } 1063 | return -1 1064 | } 1065 | 1066 | for i := 0; i < n; i++ { 1067 | m[i] = sm[i + 64] 1068 | } 1069 | 1070 | mlen = n 1071 | return mlen 1072 | 1073 | } 1074 | 1075 | // Converts Curve25519 public key back to Ed25519 public key. 1076 | // edwardsY = (montgomeryX - 1) / (montgomeryX + 1) 1077 | func convertPublicKey(pk []uint8) []uint8 { 1078 | var z = make([]uint8, 32) 1079 | var x = gf() 1080 | var a = gf() 1081 | var b = gf() 1082 | 1083 | unpack25519(x, pk) 1084 | 1085 | A(a, x, gf1) 1086 | Z(b, x, gf1) 1087 | inv25519(a, a) 1088 | M(a, a, b) 1089 | 1090 | pack25519(z, a) 1091 | return z 1092 | } 1093 | 1094 | func curve25519_sign_open(m []uint8, sm []uint8, n int, pk []uint8) int { 1095 | // Convert Curve25519 public key into Ed25519 public key. 1096 | var edpk = convertPublicKey(pk) 1097 | 1098 | // Restore sign bit from signature. 1099 | edpk[31] = edpk[31] | ( sm[63] & 128) 1100 | 1101 | // Remove sign bit from signature. 1102 | var _sm = sm[:] 1103 | 1104 | _sm[63] = _sm[63] & 127 1105 | 1106 | // Verify signed message. 1107 | return crypto_sign_open(m, _sm, n, edpk) 1108 | } 1109 | 1110 | /* AxlSign */ 1111 | 1112 | func SharedKey(secretKey []uint8, publicKey []uint8) []uint8 { 1113 | var sharedKey = make([]uint8, 32) 1114 | crypto_scalarmult(sharedKey, secretKey, publicKey) 1115 | return sharedKey 1116 | } 1117 | 1118 | func SignMessage(secretKey []uint8, msg []uint8, opt_random []uint8) []uint8 { 1119 | if (opt_random != nil ) { 1120 | var buf = make([]uint8, 128 + len(msg)) 1121 | curve25519_sign(buf, msg, len(msg), secretKey, opt_random) 1122 | return buf[0:64 + len(msg)] 1123 | } else { 1124 | var signedMsg = make([]uint8, 64 + len(msg)) 1125 | curve25519_sign(signedMsg, msg, len(msg), secretKey, nil) 1126 | return signedMsg 1127 | } 1128 | } 1129 | 1130 | func OpenMessage(publicKey []uint8, signedMsg []uint8) []uint8 { 1131 | var tmp = make([]uint8, len(signedMsg) ) 1132 | var mlen = curve25519_sign_open(tmp, signedMsg, len(signedMsg), publicKey) 1133 | if (mlen < 0) { 1134 | return nil 1135 | } 1136 | var m = make([]uint8, mlen) 1137 | for i := 0; i < len(m); i++ { 1138 | m[i] = tmp[i] 1139 | } 1140 | return m 1141 | } 1142 | 1143 | // add by Miguel 1144 | func OpenMessageStr(publicKey []uint8, signedMsg []uint8) string { 1145 | var m = OpenMessage(publicKey, signedMsg) 1146 | return string(m) 1147 | } 1148 | 1149 | func Sign(secretKey []uint8, msg []uint8, opt_random []uint8 ) []uint8 { 1150 | var _len = 64 1151 | if (opt_random != nil) { 1152 | _len = 128 1153 | } 1154 | var buf = make([]uint8, _len + len(msg)) 1155 | 1156 | curve25519_sign(buf, msg, len(msg), secretKey, opt_random) 1157 | 1158 | var signature = make([]uint8, 64 ) 1159 | for i := 0; i < len(signature); i++ { 1160 | signature[i] = buf[i] 1161 | } 1162 | return signature 1163 | } 1164 | 1165 | func Verify(publicKey []uint8, msg []uint8, signature []uint8) int { 1166 | var sm = make([]uint8, 64 + len(msg) ) 1167 | var m = make([]uint8, 64 + len(msg) ) 1168 | 1169 | for i := 0; i < 64; i++ { 1170 | sm[i] = signature[i] 1171 | } 1172 | 1173 | for i := 0; i < len(msg); i++ { 1174 | sm[i+64] = msg[i] 1175 | } 1176 | 1177 | if ( curve25519_sign_open(m, sm, len(sm), publicKey) >= 0 ) { 1178 | return 1 1179 | } else { 1180 | return 0 1181 | } 1182 | } 1183 | 1184 | type Keys struct { 1185 | PublicKey []uint8 1186 | PrivateKey []uint8 1187 | } 1188 | 1189 | func GenerateKeyPair(seed []uint8) Keys { 1190 | var sk = make([]uint8, 32 ) 1191 | var pk = make([]uint8, 32 ) 1192 | 1193 | for i := 0; i < 32; i++ { 1194 | sk[i] = seed[i] 1195 | } 1196 | 1197 | crypto_scalarmult_base(pk, sk) 1198 | 1199 | // Turn secret key into the correct format. 1200 | sk[0] = sk[0] & 248 1201 | sk[31] = sk[31] & 127 1202 | sk[31] = sk[31] | 64 1203 | 1204 | // Remove sign bit from public key. 1205 | pk[31] = pk[31] & 127 1206 | 1207 | return Keys {pk, sk} 1208 | 1209 | } 1210 | 1211 | /* 1212 | func debugA8(t string, a []uint8) { 1213 | fmt.Printf(t + " [%d] ", len(a)) 1214 | var sum = 0 1215 | for i := 0; i< len(a); i++ { 1216 | sum += int(a[i]) 1217 | fmt.Printf("%d ", a[i]) 1218 | } 1219 | fmt.Printf(" - suma: %d\n\n", sum) 1220 | } 1221 | */ 1222 | -------------------------------------------------------------------------------- /test/test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | import "math/rand" 5 | import "curve25519-go/axlsign" 6 | import b64 "encoding/base64" 7 | import "time" 8 | 9 | func randomBytes(size int) []uint8 { 10 | rand.Seed(time.Now().UTC().UnixNano()) 11 | var High int = 255 12 | var seed = make([]uint8, size ) 13 | for i := 0; i < len(seed); i++ { 14 | seed[i] = uint8(rand.Int() % (High + 1)) 15 | } 16 | return seed 17 | } 18 | 19 | func main() { 20 | fmt.Println("\nHello, curve25519\n") 21 | 22 | // random seed 23 | var seed = randomBytes(32) 24 | 25 | // generate key pair 26 | var keys = axlsign.GenerateKeyPair(seed) 27 | 28 | var texto = "¡ lo esencial es invisible a los ojos !..." 29 | var rnd = randomBytes(64) 30 | var msg = []uint8( texto ) 31 | var sig = axlsign.Sign(keys.PrivateKey, msg, rnd) // firmar 32 | var res = axlsign.Verify(keys.PublicKey, msg, sig) // control ok 33 | var res1 = axlsign.Verify(keys.PrivateKey, msg, sig) // control error 34 | 35 | var sigmsg = axlsign.SignMessage(keys.PrivateKey, msg, rnd) 36 | // var msg2 = axlsign.OpenMessage(keys.PublicKey, sigmsg) 37 | var smsg = axlsign.OpenMessageStr(keys.PublicKey, sigmsg) 38 | 39 | // controles 40 | 41 | fmt.Printf("Res: %d\nRes2: %d\n", res, res1) 42 | fmt.Println(texto) 43 | fmt.Println(smsg) 44 | 45 | // Control 46 | 47 | var b64sk, _ = b64.StdEncoding.DecodeString( "QEK6Xm/ourxQVlBzaOdVxYBeew8dlQ7dYrqEI60ksmo=" ) 48 | var b64pk, _ = b64.StdEncoding.DecodeString( "yScViZr67HSpb5mWG/Ij0yCFAmwCqdYB9nxLasej/0g=" ) 49 | 50 | var sk = []uint8( b64sk ) // privada 51 | var pk = []uint8( b64pk ) // publica 52 | var shared = axlsign.SharedKey(sk, pk) 53 | 54 | texto = "PRUEBA FIRMA" 55 | 56 | rnd = []uint8( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ) 57 | msg = []uint8( texto ) 58 | sig = axlsign.Sign(sk, msg, rnd) // firmar 59 | seed = []uint8( "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ) // 32 60 | 61 | keys = axlsign.GenerateKeyPair(seed) 62 | sigmsg = axlsign.SignMessage(keys.PrivateKey, msg, rnd) 63 | smsg = axlsign.OpenMessageStr(keys.PublicKey, sigmsg) 64 | 65 | // LOG 66 | fmt.Println("sk: " + b64.StdEncoding.EncodeToString(sk) ) 67 | fmt.Println("pk: " + b64.StdEncoding.EncodeToString(pk) ) 68 | fmt.Println("shared: " + b64.StdEncoding.EncodeToString(shared) ) 69 | fmt.Println("sig: " + b64.StdEncoding.EncodeToString(sig) ) 70 | fmt.Println("sig+msg: " + b64.StdEncoding.EncodeToString(sigmsg) ) 71 | fmt.Println("msg: " + smsg ) 72 | 73 | } 74 | --------------------------------------------------------------------------------