Add utility procedures for SECIO.

Add 2 more length encodings for protobuf.
This commit is contained in:
cheatfate 2019-09-09 19:57:17 +03:00
parent c584583678
commit f2b10776db
No known key found for this signature in database
GPG Key ID: 46ADD633A7201F95
2 changed files with 78 additions and 1 deletions

View File

@ -8,6 +8,7 @@
## those terms.
## This module implements Public Key and Private Key interface for libp2p.
import strutils
import rsa, ecnist, ed25519/ed25519, secp
import ../protobuf/minprotobuf, ../vbuffer
import nimcrypto/[rijndael, blowfish, sha, sha2, hash, hmac, utils]
@ -572,6 +573,63 @@ proc makeSecret*(remoteEPublic: PublicKey, localEPrivate: PrivateKey,
if localEPrivate.scheme == remoteEPublic.scheme:
result = toSecret(remoteEPublic.eckey, localEPrivate.eckey, data)
proc getOrder*(remotePubkey, localNonce: openarray[byte],
localPubkey, remoteNonce: openarray[byte]): int =
## Compare values and calculate `order` parameter.
var ctx: sha256
ctx.init()
ctx.update(remotePubkey)
ctx.update(localNonce)
var digest1 = ctx.finish()
ctx.init()
ctx.update(localPubkey)
ctx.update(remoteNonce)
var digest2 = ctx.finish()
var diff = 0
for i in 0 ..< len(digest1.data):
diff = int(digest1.data[i]) - int(digest2.data[i])
result = (result and -not(diff)) or diff
proc selectBest*(order: int, p1, p2: string): string =
## Determines which algorithm to use from list `p1` and `p2`.
##
## Returns empty string if there no algorithms in common.
var f, s: seq[string]
if order < 0:
f = strutils.split(p2, ",")
s = strutils.split(p1, ",")
elif order > 0:
f = strutils.split(p1, ",")
s = strutils.split(p2, ",")
else:
var p = strutils.split(p1, ",")
result = p[0]
return
for felement in f:
for selement in s:
if felement == selement:
result = felement
break
proc createProposal*(nonce, pubkey: openarray[byte],
exchanges, ciphers, hashes: string): seq[byte] =
var msg = initProtoBuffer({WithUint32BeLength})
msg.write(initProtoField(1, nonce))
msg.write(initProtoField(2, pubkey))
msg.write(initProtoField(3, exchanges))
msg.write(initProtoField(4, ciphers))
msg.write(initProtoField(5, hashes))
msg.finish()
shallowCopy(result, msg.buffer)
proc createExchange*(epubkey, signature: openarray[byte]): seq[byte] =
var msg = initProtoBuffer({WithUint32BeLength})
msg.write(initProtoField(1, epubkey))
msg.write(initProtoField(2, signature))
msg.finish()
shallowCopy(result, msg.buffer)
## Serialization/Deserialization helpers
proc write*(vb: var VBuffer, pubkey: PublicKey) {.inline.} =

View File

@ -20,7 +20,7 @@ type
ProtoFlags* = enum
## Protobuf's encoding types
WithVarintLength
WithVarintLength, WithUint32BeLength, WithUint32LeLength
ProtoBuffer* = object
## Protobuf's message representation object
@ -128,6 +128,11 @@ proc initProtoBuffer*(options: set[ProtoFlags] = {}): ProtoBuffer =
# in [0, 9].
result.buffer.setLen(10)
result.offset = 10
elif {WithUint32LeLength, WithUint32BeLength} * options != {}:
# Our buffer will start from position 4, so we can store length of buffer
# in [0, 9].
result.buffer.setLen(4)
result.offset = 4
proc write*(pb: var ProtoBuffer, field: ProtoField) =
## Encode protobuf's field ``field`` and store it to protobuf's buffer ``pb``.
@ -184,6 +189,20 @@ proc finish*(pb: var ProtoBuffer) =
let res = PB.putUVarint(pb.buffer.toOpenArray(pos, 9), usedBytes, size)
doAssert(res == VarintStatus.Success)
pb.offset = pos
elif WithUint32BeLength in pb.options:
let size = uint(len(pb.buffer) - 4)
pb.buffer[0] = byte(size shr 24)
pb.buffer[1] = byte(size shr 16)
pb.buffer[2] = byte(size shr 8)
pb.buffer[3] = byte(size)
pb.offset = 4
elif WithUint32LeLength in pb.options:
let size = uint(len(pb.buffer) - 4)
pb.buffer[0] = byte(size)
pb.buffer[1] = byte(size shr 8)
pb.buffer[2] = byte(size shr 16)
pb.buffer[3] = byte(size shr 24)
pb.offset = 4
else:
pb.offset = 0