Skip to content

Commit

Permalink
test: add tests for invalid signature inputs and Koblitz encoding/dec…
Browse files Browse the repository at this point in the history
…oding
  • Loading branch information
isakruas committed Oct 27, 2024
1 parent 8f24242 commit 36b9004
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/algorithms.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export class DigitalSignature {
* @returns {boolean} True if the signature is valid, false otherwise.
*/
verify_signature(public_key, message_hash, r, s) {
if (!(1 <= r < this.curve.n && 1 <= s < this.curve.n)) {
if (r < 1n || r >= this.curve.n || s < 1n || s >= this.curve.n) {
throw new Error('r or s are not in the valid range [1, curve order - 1].')
}

Expand Down
40 changes: 38 additions & 2 deletions src/algorithms.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,54 @@ test('digital-signature: generate and verify signature', () => {

test('digital-signature: verify signature with invalid inputs', () => {
const message_hash = BigInt(545454445644654n)
const signature = ds.generate_signature(message_hash)

// Choose invalid r and s values (outside the range [1, n-1])
const invalid_r = ds.curve.n
const invalid_s = BigInt(0)

// Check that the appropriate exception is raised for invalid r and s
expect(() => {
ds.verify_signature(ds.public_key, message_hash, invalid_r, invalid_s)
}).toThrowError()
ds.verify_signature(
ds.public_key,
message_hash,
invalid_r,
BigInt(signature[1]),
)
}).toThrowError('r or s are not in the valid range [1, curve order - 1].')

expect(() => {
ds.verify_signature(
ds.public_key,
message_hash,
BigInt(signature[0]),
invalid_s,
)
}).toThrowError('r or s are not in the valid range [1, curve order - 1].')
})

const encoder = new Koblitz('secp521r1')
const decoder = new Koblitz('secp521r1')

test('koblitz: encode throws error for unsupported alphabet size', () => {
const encoder = new Koblitz()
const message = 'Test message'

expect(() => {
encoder.encode(message, 250n)
}).toThrow('Alphabet size not supported')
})

test('koblitz: decode throws error for unsupported alphabet size', () => {
const decoder = new Koblitz()
const point = { x: 1n, y: 1n }
const j = 0n

expect(() => {
decoder.decode(point, j, 250n)
}).toThrow('Alphabet size not supported')
})

test('koblitz: encode and decode ascii', () => {
const message = 'Hello, EC!'
const encode = encoder.encode(message, 2n ** 8n)
Expand Down
2 changes: 1 addition & 1 deletion src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class EllipticCurveOperations {
* @returns {Point} The resulting point.
*/
multiply_point(k, P) {
if (typeof k !== 'bigint' || k <= 0n || k >= this.n) {
if (typeof k !== 'bigint' || k < 1n || k >= this.n) {
throw new Error('k is not in the range 0 < k < n')
}

Expand Down
75 changes: 56 additions & 19 deletions src/protocols.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { test, expect } from '@jest/globals'
import { DiffieHellman, MasseyOmura } from './protocols'
import { Koblitz } from './algorithms'
import { Point } from './core'

test('diffie-hellman: compute shared secret', () => {
const private_key_alice = 12345n
Expand All @@ -18,31 +20,66 @@ test('diffie-hellman: compute shared secret', () => {
})

test('massey-omura: encryption decryption', () => {
const private_key_sender = 123456n
const mo_sender = new MasseyOmura(private_key_sender)
// Initialize the Koblitz instance for the elliptic curve 'secp192k1'
const koblitz = new Koblitz('secp192k1')

const private_key_receiver = 654321n
const mo_receiver = new MasseyOmura(private_key_receiver)
// Sender's side
// -------------
const privateKeySender = BigInt('70604135')
// Initialize Massey-Omura protocol with the sender's private key
const moSender = new MasseyOmura(privateKeySender)

const message = mo_sender.curve.G // Using the curve's generator point for simplicity
// Encode the message using the Koblitz method
// `j` is used to handle the ambiguity in the decoding process
const [message, j] = koblitz.encode('Hello, world!')

// Sender encrypts the message
const encrypted_by_sender = mo_sender.first_encryption_step(message)
// Perform the first encryption step with Massey-Omura protocol
const encryptedMsgSender = moSender.first_encryption_step(message)

// Receiver encrypts the already encrypted message
const encrypted_by_receiver =
mo_receiver.second_encryption_step(encrypted_by_sender)
// The encoded message is now sent to the receiver...
// (transmission of encryptedMsgSender)

// Sender decrypts the message partly
const partially_decrypted_by_sender = mo_sender.partial_decryption_step(
encrypted_by_receiver,
)
// Receiver's side
// ---------------
const privateKeyReceiver = BigInt('48239108668')
// Initialize Massey-Omura protocol with the receiver's private key
const moReceiver = new MasseyOmura(privateKeyReceiver)

// Receiver completes decryption
const fully_decrypted_message = mo_receiver.partial_decryption_step(
partially_decrypted_by_sender,
)
// Perform the second encryption step with Massey-Omura protocol
const encryptedMsgReceiver =
moReceiver.second_encryption_step(encryptedMsgSender)

// The double-encrypted message is sent back to the sender...
// (transmission of encryptedMsgReceiver)

// Sender's side again
// -------------------
const partialDecryptedMsg =
moSender.partial_decryption_step(encryptedMsgReceiver)

// The partially decrypted message is sent back to the receiver...
// (transmission of partialDecryptedMsg)

// Receiver's final decryption
// ---------------------------
const originalMessage =
moReceiver.partial_decryption_step(partialDecryptedMsg)

// Decode the message using the Koblitz method
// `j` is used to resolve the mapping from the elliptic curve point back to the message
const decodedMessage = koblitz.decode(originalMessage, j)

// The fully decrypted message should match the original message
expect(fully_decrypted_message).toStrictEqual(message)
expect(decodedMessage).toStrictEqual('Hello, world!')
})

test('massey-omura: validate the public key value', () => {
const moSender = new MasseyOmura(654564n)

const P1 = new Point(
2561645154652864168258282342383115659685709191094067233983n,
89709827696035605786509950363037856155865475850237621433n,
)

expect(moSender.public_key.toString()).toStrictEqual(P1.toString())
})

0 comments on commit 36b9004

Please sign in to comment.