mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2026-01-20 20:01:22 +00:00
Fix http signature unit test
This commit is contained in:
parent
a9963fb1a9
commit
c2c9e98787
@ -1,69 +1,84 @@
|
||||
import { createSignature, verifySignature } from '.'
|
||||
import Factory from '../../seed/factories'
|
||||
import { host, login } from '../../jest/helpers'
|
||||
import { GraphQLClient } from 'graphql-request'
|
||||
import { generateRsaKeyPair, createSignature, verifySignature } from '.'
|
||||
import crypto from 'crypto'
|
||||
import { expect } from 'chai'
|
||||
const factory = Factory()
|
||||
jest.mock('request')
|
||||
import request from 'request'
|
||||
|
||||
describe('Signature creation and verification', () => {
|
||||
let user = null
|
||||
let client = null
|
||||
const headers = {
|
||||
'Date': '2019-03-08T14:35:45.759Z',
|
||||
'Host': 'democracy-app.de',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
let privateKey
|
||||
let publicKey
|
||||
let headers
|
||||
const passphrase = "a7dsf78sadg87ad87sfagsadg78"
|
||||
|
||||
beforeEach(async () => {
|
||||
await factory.create('User', {
|
||||
'slug': 'test-user',
|
||||
'name': 'Test User',
|
||||
'email': 'user@example.org',
|
||||
'password': 'swordfish'
|
||||
describe('activityPub/security', () => {
|
||||
beforeEach(() => {
|
||||
const pair = generateRsaKeyPair({passphrase})
|
||||
privateKey = pair.privateKey
|
||||
publicKey = pair.publicKey
|
||||
headers = {
|
||||
'Date': '2019-03-08T14:35:45.759Z',
|
||||
'Host': 'democracy-app.de',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
describe('createSignature', () => {
|
||||
describe('returned http signature', () => {
|
||||
let signatureB64
|
||||
let httpSignature
|
||||
|
||||
beforeEach(() => {
|
||||
const signer = crypto.createSign('rsa-sha256')
|
||||
signer.update('(request-target): post /activitypub/users/max/inbox\ndate: 2019-03-08T14:35:45.759Z\nhost: democracy-app.de\ncontent-type: application/json')
|
||||
signatureB64 = signer.sign({ key: privateKey, passphrase: 'a7dsf78sadg87ad87sfagsadg78' }, 'base64')
|
||||
httpSignature = createSignature({privateKey, keyId: 'https://human-connection.org/activitypub/users/lea#main-key', url: 'https://democracy-app.de/activitypub/users/max/inbox', headers, passphrase})
|
||||
})
|
||||
|
||||
it('contains keyId', () => {
|
||||
expect(httpSignature).toContain('keyId="https://human-connection.org/activitypub/users/lea#main-key"')
|
||||
})
|
||||
|
||||
it('contains default algorithm "rsa-sha256"', () => {
|
||||
expect(httpSignature).toContain('algorithm="rsa-sha256"')
|
||||
})
|
||||
|
||||
it('contains headers', () => {
|
||||
expect(httpSignature).toContain('headers="(request-target) date host content-type"')
|
||||
})
|
||||
|
||||
it('contains signature', () => {
|
||||
expect(httpSignature).toContain('signature="' + signatureB64 + '"')
|
||||
})
|
||||
})
|
||||
const headers = await login({ email: 'user@example.org', password: 'swordfish' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
const result = await client.request(`query {
|
||||
User(slug: "test-user") {
|
||||
privateKey
|
||||
publicKey
|
||||
})
|
||||
|
||||
describe('verifySignature', () => {
|
||||
let httpSignature
|
||||
|
||||
beforeEach(() => {
|
||||
httpSignature = createSignature({privateKey, keyId: 'http://localhost:4001/activitypub/users/test-user#main-key', url: 'https://democracy-app.de/activitypub/users/max/inbox', headers, passphrase})
|
||||
const body = {
|
||||
"publicKey":{
|
||||
"id":"https://localhost:4001/activitypub/users/test-user#main-key",
|
||||
"owner":"https://localhost:4001/activitypub/users/test-user",
|
||||
"publicKeyPem": publicKey
|
||||
}
|
||||
}
|
||||
}`)
|
||||
user = result.User[0]
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await factory.cleanDatabase()
|
||||
})
|
||||
|
||||
describe('Signature creation', () => {
|
||||
let signatureB64 = ''
|
||||
beforeEach(() => {
|
||||
const signer = crypto.createSign('rsa-sha256')
|
||||
signer.update('(request-target): post /activitypub/users/max/inbox\ndate: 2019-03-08T14:35:45.759Z\nhost: democracy-app.de\ncontent-type: application/json')
|
||||
signatureB64 = signer.sign({ key: user.privateKey, passphrase: 'a7dsf78sadg87ad87sfagsadg78' }, 'base64')
|
||||
})
|
||||
it('creates a Signature with given privateKey, keyId, url and headers (default algorithm: "rsa-sha256")', () => {
|
||||
const httpSignature = createSignature(user.privateKey, 'https://human-connection.org/activitypub/users/lea#main-key', 'https://democracy-app.de/activitypub/users/max/inbox', headers)
|
||||
|
||||
expect(httpSignature).to.contain('keyId="https://human-connection.org/activitypub/users/lea#main-key"')
|
||||
expect(httpSignature).to.contain('algorithm="rsa-sha256"')
|
||||
expect(httpSignature).to.contain('headers="(request-target) date host content-type"')
|
||||
expect(httpSignature).to.contain('signature="' + signatureB64 + '"')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Signature verification', () => {
|
||||
let httpSignature = ''
|
||||
beforeEach(() => {
|
||||
httpSignature = createSignature(user.privateKey, 'http://localhost:4001/activitypub/users/test-user#main-key', 'https://democracy-app.de/activitypub/users/max/inbox', headers)
|
||||
const mockedRequest = jest.fn((_, callback) => callback(null, null, JSON.stringify(body)))
|
||||
request.mockImplementation(mockedRequest)
|
||||
})
|
||||
|
||||
it('verifies a Signature correct', async () => {
|
||||
headers['Signature'] = httpSignature
|
||||
const isVerified = await verifySignature('https://democracy-app.de/activitypub/users/max/inbox', headers)
|
||||
expect(isVerified).to.equal(true)
|
||||
it('resolves false', async () => {
|
||||
await expect(verifySignature('https://democracy-app.de/activitypub/users/max/inbox', headers)).resolves.toEqual(false)
|
||||
})
|
||||
|
||||
describe('valid signature', () => {
|
||||
beforeEach(() => {
|
||||
headers.Signature = httpSignature
|
||||
})
|
||||
|
||||
it('resolves true', async () => {
|
||||
await expect(verifySignature('https://democracy-app.de/activitypub/users/max/inbox', headers)).resolves.toEqual(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -6,7 +6,8 @@ const debug = require('debug')('ea:security')
|
||||
|
||||
dotenv.config({ path: resolve('src', 'activitypub', '.env') })
|
||||
|
||||
export function generateRsaKeyPair () {
|
||||
export function generateRsaKeyPair (options = {}) {
|
||||
const { passphrase = process.env.PRIVATE_KEY_PASSPHRASE } = options
|
||||
return crypto.generateKeyPairSync('rsa', {
|
||||
modulusLength: 4096,
|
||||
publicKeyEncoding: {
|
||||
@ -17,18 +18,24 @@ export function generateRsaKeyPair () {
|
||||
type: 'pkcs8',
|
||||
format: 'pem',
|
||||
cipher: 'aes-256-cbc',
|
||||
passphrase: process.env.PRIVATE_KEY_PASSPHRASE
|
||||
passphrase
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// signing
|
||||
export function createSignature (privKey, keyId, url, headers = {}, algorithm = 'rsa-sha256') {
|
||||
export function createSignature (options) {
|
||||
const {
|
||||
privateKey, keyId, url,
|
||||
headers = {},
|
||||
algorithm = 'rsa-sha256',
|
||||
passphrase = process.env.PRIVATE_KEY_PASSPHRASE
|
||||
} = options
|
||||
if (!SUPPORTED_HASH_ALGORITHMS.includes(algorithm)) { throw Error(`SIGNING: Unsupported hashing algorithm = ${algorithm}`) }
|
||||
const signer = crypto.createSign(algorithm)
|
||||
const signingString = constructSigningString(url, headers)
|
||||
signer.update(signingString)
|
||||
const signatureB64 = signer.sign({ key: privKey, passphrase: process.env.PRIVATE_KEY_PASSPHRASE }, 'base64')
|
||||
const signatureB64 = signer.sign({ key: privateKey, passphrase }, 'base64')
|
||||
const headersString = Object.keys(headers).reduce((result, key) => { return result + ' ' + key.toLowerCase() }, '')
|
||||
return `keyId="${keyId}",algorithm="${algorithm}",headers="(request-target)${headersString}",signature="${signatureB64}"`
|
||||
}
|
||||
|
||||
@ -75,12 +75,13 @@ export function signAndSend (activity, fromName, targetDomain, url) {
|
||||
headers: {
|
||||
'Host': targetDomain,
|
||||
'Date': date,
|
||||
'Signature': createSignature(privateKey, `http://${activityPub.domain}/activitypub/users/${fromName}#main-key`, url,
|
||||
{
|
||||
'Signature': createSignature({privateKey, keyId: `http://${activityPub.domain}/activitypub/users/${fromName}#main-key`, url,
|
||||
headers: {
|
||||
'Host': targetDomain,
|
||||
'Date': date,
|
||||
'Content-Type': 'application/activity+json'
|
||||
}),
|
||||
}
|
||||
}),
|
||||
'Content-Type': 'application/activity+json'
|
||||
},
|
||||
method: 'POST',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user