Skip to content

Commit

Permalink
2.4.1 fix generateKey & decrypt
Browse files Browse the repository at this point in the history
add missing validation of authentication
  • Loading branch information
smcatala committed Aug 25, 2018
1 parent 249f220 commit 1a0203b
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 48 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,14 @@ it is in fact fully async.

the files of this example are available [in the `example` folder](./spec/example).

a live version of this example can be viewed [in the browser console](https://cdn.rawgit.com/ZenyWay/opgp-service/v2.4.0/spec/example/index.html),
a live version of this example can be viewed [in the browser console](https://cdn.rawgit.com/ZenyWay/opgp-service/v2.4.1/spec/example/index.html),
or by cloning this repository and running the following commands from a terminal:
```bash
npm install
npm run example
```

# <a name="api"></a> API 2.3 stable
# <a name="api"></a> API 2.4 stable
the current version exposes the following service methods:
* configure
* isValidKeyHandle, generateKey, getPublicKey, getKeysFromArmor, getArmorFromKey
Expand All @@ -100,7 +100,7 @@ the current version exposes the following service methods:
* sign, verify

for a detailed specification of the API
* run the [unit tests](https://cdn.rawgit.com/ZenyWay/opgp-service/v2.4.0/spec/web/index.html)
* run the [unit tests](https://cdn.rawgit.com/ZenyWay/opgp-service/v2.4.1/spec/web/index.html)
in your browser,
* or check the [public interface declaration](./src/index.ts#L26-L469)
in the source code.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "opgp-service",
"version": "2.4.0",
"version": "2.4.1",
"description": "a fully async API for openpgp that builds on ephemeral immutable keys and that does not leak cryptographic material. ES5. Typescript support. 36kB gzip, excluding openpgp",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion spec/example/index.js

Large diffs are not rendered by default.

102 changes: 99 additions & 3 deletions spec/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,11 @@ describe('OpgpService', () => {
.catch(() => { /* no operation */ }) // ignore
.finally(() => {
expect(openpgp.key.generate).toHaveBeenCalledWith(jasmine.objectContaining({
userIds: jasmine.arrayContaining([ 'john.doe@test.com' ]),
userIds: [ 'john.doe@test.com' ],
passphrase: 'secret passphrase',
numBits: 4096,
unlocked: false
subkeys: [{}],
keyExpirationTime: 0
}))
setTimeout(done)
})
Expand Down Expand Up @@ -288,6 +289,41 @@ describe('OpgpService', () => {
expect(result).toEqual(jasmine.objectContaining(livekey.bp))
expect(error).not.toBeDefined()
})

describe('when `opts.unlocked` is `true`', function () {
let error: any
let result: any

beforeEach(() => {
result = []
livekey.key.decrypt = jasmine.createSpy('decrypt')
.and.callFake(function () {
result.push('decrypt')
return Promise.resolve(true)
})
getLiveKey.and.callFake(function () {
result.push('get-live-key')
return Promise.resolve(livekey)
})
})

beforeEach((done) => {
service.generateKey('john.doe@test.com', { unlocked: true })
.then((res: any) => result.push(res))
.catch((err: any) => error = err)
.finally(() => setTimeout(done))
})

it('unlocks the new openpgp key before creating ' +
'the corresponding {OpgpLiveKey}', function () {
expect(getLiveKey).toHaveBeenCalledWith(livekey.key)
expect(result).toEqual([
'decrypt',
'get-live-key',
jasmine.objectContaining({ handle: 'key-handle' })
])
})
})
})

describe('when the underlying openpgp primitive throws an error', () => {
Expand Down Expand Up @@ -1159,7 +1195,13 @@ describe('OpgpService', () => {
livekey.bp.isLocked = false
cache.get.and.returnValue(livekey)
openpgp.message.readArmored.and.returnValue(message)
openpgp.decrypt.and.returnValue({ data: 'plain text' })
openpgp.decrypt.and.returnValue({
data: 'plain text',
signatures: [{
keyid: 'valid-auth-key-handle',
valid: true
}]
})
})

beforeEach((done) => {
Expand Down Expand Up @@ -1276,6 +1318,60 @@ describe('OpgpService', () => {
})
})

describe('when given a valid cipher text string with an invalid signature',
() => {
let error: any
let result: any
beforeEach(() => {
livekey.bp.isLocked = false
cache.get.and.returnValue(livekey)
openpgp.message.readArmored.and.returnValue(message)
openpgp.decrypt.and.returnValue({
data: 'plain text',
signatures: [{
keyid: 'auth-key-id',
valid: false
}]
})
})

beforeEach((done) => {
const refs = {
cipher: 'valid-cipher-key-handle',
auth: 'valid-auth-key-handle'
}
service.decrypt(Promise.resolve(refs), 'cipher text')
.then((res: any) => result = res)
.catch((err: any) => error = err)
.finally(() => setTimeout(done))
})

it('retrieves the {OpgpLiveKey} instances ' +
'referenced by the given handles when compliant', () => {
expect(cache.get.calls.allArgs()).toEqual([
[ 'valid-cipher-key-handle' ],
[ 'valid-auth-key-handle' ]
])
})

it('delegates to the openpgp primitive', () => {
expect(openpgp.message.readArmored).toHaveBeenCalledWith('cipher text')
expect(openpgp.decrypt)
.toHaveBeenCalledWith(jasmine.objectContaining({
message: message,
publicKeys: [ livekey.key ],
privateKeys: livekey.key
}))
})

it('returns a Promise that rejects ' +
'with an `authentication failed: {authKeyId}` {Error}', () => {
expect(result).not.toBeDefined()
expect(error).toBeDefined()
expect(error.message).toBe('authentication failed: auth-key-id')
})
})

describe('when the underlying openpgp primitive rejects with an {Error}', () => {
let error: any
let result: any
Expand Down
2 changes: 1 addition & 1 deletion spec/web/index.spec.js

Large diffs are not rendered by default.

Loading

0 comments on commit 1a0203b

Please sign in to comment.