Implement hkp index/mr
This commit is contained in:
parent
e60c6ed8c5
commit
20145d3a11
18
README.md
18
README.md
@ -55,26 +55,26 @@ keytext=-----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK--
|
|||||||
|
|
||||||
### Lookup a key
|
### Lookup a key
|
||||||
|
|
||||||
Currently only the `get` operation is implemented. Other operations will return a `501` (not implemented) http error code.
|
Currently only the `get` and `index` (with options=mr) operations are implemented. Other operations will return a `501` (not implemented) http error code.
|
||||||
|
|
||||||
#### By key id
|
#### By key id (get)
|
||||||
|
|
||||||
```
|
```
|
||||||
GET /pks/lookup?op=get&search=0x0123456789ABCDEF
|
GET /pks/lookup?op=get&search=0x0123456789ABCDEF
|
||||||
```
|
```
|
||||||
|
|
||||||
#### By email address
|
#### By email address (get, mr)
|
||||||
|
|
||||||
```
|
|
||||||
GET /pks/lookup?op=get&search=user@example.com
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Machine readable
|
|
||||||
|
|
||||||
```
|
```
|
||||||
GET /pks/lookup?op=get&options=mr&search=user@example.com
|
GET /pks/lookup?op=get&options=mr&search=user@example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### By key id (index, mr)
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /pks/lookup?op=index&options=mr&search=0x0123456789ABCDEF
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## REST api
|
## REST api
|
||||||
|
@ -57,7 +57,7 @@ class HKP {
|
|||||||
let params = this.parseQueryString(ctx);
|
let params = this.parseQueryString(ctx);
|
||||||
let key = yield this._publicKey.get(params);
|
let key = yield this._publicKey.get(params);
|
||||||
this.setGetHeaders(ctx, params);
|
this.setGetHeaders(ctx, params);
|
||||||
ctx.body = key.publicKeyArmored;
|
this.setGetBody(ctx, params, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,7 +77,7 @@ class HKP {
|
|||||||
params.email = ctx.query.search;
|
params.email = ctx.query.search;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.op !== 'get') {
|
if ((params.op !== 'get' && params.op !== 'index') || (params.op === 'index' && !params.mr)) {
|
||||||
ctx.throw(501, 'Not implemented!');
|
ctx.throw(501, 'Not implemented!');
|
||||||
} else if (!params.keyid && !params.email) {
|
} else if (!params.keyid && !params.email) {
|
||||||
ctx.throw(400, 'Invalid request!');
|
ctx.throw(400, 'Invalid request!');
|
||||||
@ -105,12 +105,37 @@ class HKP {
|
|||||||
* @param {Object} params The parsed query string parameters
|
* @param {Object} params The parsed query string parameters
|
||||||
*/
|
*/
|
||||||
setGetHeaders(ctx, params) {
|
setGetHeaders(ctx, params) {
|
||||||
if (params.mr) {
|
if (params.op === 'get' && params.mr) {
|
||||||
ctx.set('Content-Type', 'application/pgp-keys; charset=UTF-8');
|
ctx.set('Content-Type', 'application/pgp-keys; charset=utf-8');
|
||||||
ctx.set('Content-Disposition', 'attachment; filename=openpgpkey.asc');
|
ctx.set('Content-Disposition', 'attachment; filename=openpgpkey.asc');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the body accordingly.
|
||||||
|
* See https://tools.ietf.org/html/draft-shaw-openpgp-hkp-00#section-5
|
||||||
|
* @param {Object} ctx The koa request/response context
|
||||||
|
* @param {Object} params The parsed query string parameters
|
||||||
|
* @param {Object} key The public key document
|
||||||
|
*/
|
||||||
|
setGetBody(ctx, params, key) {
|
||||||
|
if (params.op === 'get') {
|
||||||
|
ctx.body = key.publicKeyArmored;
|
||||||
|
} else if (params.op === 'index' && params.mr) {
|
||||||
|
const VERSION = 1;
|
||||||
|
const COUNT = 1; // number of keys
|
||||||
|
let algo = (key.algorithm.indexOf('rsa') !== -1) ? 1 : '';
|
||||||
|
let created = key.created ? (key.created.getTime() / 1000) : '';
|
||||||
|
let uid = key.userIds.map(u => u.name + ' <' + u.email + '>').join(', ');
|
||||||
|
|
||||||
|
ctx.body =
|
||||||
|
'info:' + VERSION + ':' + COUNT + '\n' +
|
||||||
|
'pub:' + key.keyid + ':' + algo + ':' + key.keylen + ':' + created + '::\n' +
|
||||||
|
'uid:' + encodeURIComponent(uid) + ':' + created + '::\n' +
|
||||||
|
key.publicKeyArmored;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = HKP;
|
module.exports = HKP;
|
@ -92,9 +92,14 @@ class PublicKey {
|
|||||||
keys.forEach(key => userIds = userIds.concat(key.getUserIds()));
|
keys.forEach(key => userIds = userIds.concat(key.getUserIds()));
|
||||||
userIds = util.deDup(userIds);
|
userIds = util.deDup(userIds);
|
||||||
// get key id
|
// get key id
|
||||||
|
let primKey = keys[0].primaryKey;
|
||||||
return {
|
return {
|
||||||
keyid: keys[0].primaryKey.getKeyId().toHex().toUpperCase(),
|
keyid: primKey.getKeyId().toHex().toUpperCase(),
|
||||||
userIds: util.parseUserIds(userIds)
|
userIds: util.parseUserIds(userIds),
|
||||||
|
fingerprint: primKey.fingerprint.toUpperCase(),
|
||||||
|
created: primKey.created,
|
||||||
|
algorithm: primKey.algorithm,
|
||||||
|
keylen: primKey.getBitSize()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +160,10 @@ class PublicKey {
|
|||||||
if (!verified) {
|
if (!verified) {
|
||||||
util.throw(404, 'Key not found');
|
util.throw(404, 'Key not found');
|
||||||
}
|
}
|
||||||
return yield this._mongo.get({ _id:verified.keyid }, DB_TYPE);
|
let key = yield this._mongo.get({ _id:verified.keyid }, DB_TYPE);
|
||||||
|
let params = this._parseKey(key.publicKeyArmored);
|
||||||
|
params.publicKeyArmored = key.publicKeyArmored;
|
||||||
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -168,20 +168,14 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
it('should return 200 and get key by id', done => {
|
it('should return 200 and get key by id', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/api/v1/key?keyid=' + emailParams.keyid)
|
.get('/api/v1/key?keyid=' + emailParams.keyid)
|
||||||
.expect(200, {
|
.expect(200)
|
||||||
_id: emailParams.keyid,
|
|
||||||
publicKeyArmored
|
|
||||||
})
|
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 200 and get key email address', done => {
|
it('should return 200 and get key email address', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/api/v1/key?email=' + primaryEmail)
|
.get('/api/v1/key?email=' + primaryEmail)
|
||||||
.expect(200, {
|
.expect(200)
|
||||||
_id: emailParams.keyid,
|
|
||||||
publicKeyArmored
|
|
||||||
})
|
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -394,15 +388,23 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
|
|||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 200 for "mr" (machine readable) option', done => {
|
it('should return 200 for "mr" option', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/pks/lookup?op=get&options=mr&search=' + primaryEmail)
|
.get('/pks/lookup?op=get&options=mr&search=' + primaryEmail)
|
||||||
.expect('Content-Type', 'application/pgp-keys; charset=UTF-8')
|
.expect('Content-Type', 'application/pgp-keys; charset=utf-8')
|
||||||
.expect('Content-Disposition', 'attachment; filename=openpgpkey.asc')
|
.expect('Content-Disposition', 'attachment; filename=openpgpkey.asc')
|
||||||
.expect(200, publicKeyArmored)
|
.expect(200, publicKeyArmored)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return 200 for "index" with "mr" option', done => {
|
||||||
|
request(app.listen())
|
||||||
|
.get('/pks/lookup?op=index&options=mr&search=0x' + emailParams.keyid)
|
||||||
|
.expect('Content-Type', 'text/plain; charset=utf-8')
|
||||||
|
.expect(200)
|
||||||
|
.end(done);
|
||||||
|
});
|
||||||
|
|
||||||
it('should return 400 for invalid email', done => {
|
it('should return 400 for invalid email', done => {
|
||||||
request(app.listen())
|
request(app.listen())
|
||||||
.get('/pks/lookup?op=get&search=a@bco')
|
.get('/pks/lookup?op=get&search=a@bco')
|
||||||
|
Loading…
Reference in New Issue
Block a user