Skip to content
Snippets Groups Projects
Commit 1e656a79 authored by Dominik Hebeler's avatar Dominik Hebeler
Browse files

added api method to sign tokens

parent 97f4bf5a
No related branches found
No related tags found
No related merge requests found
Pipeline #7275 failed
...@@ -133,3 +133,39 @@ This Method does not require authentication ...@@ -133,3 +133,39 @@ This Method does not require authentication
"pubkey_pem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1knnta8kCSClaIPECAGZ\npD75MIRVD20Ucc/SQP3BFHVCoBhwLt77V3ORpwYph8Wzk9QNYjwXwme8Dd8CCdu1\noLKXbneUn3gR1f/yu2ghih64Qs7DRbIVCILDUmO3PCCePB811Dz5cBABjbUg64p3\nOJbJDtbWxcZYYd5GH3VOo0yhk7RKSZxGNzCnwtzRvhKzdl0hI5F8POA6rkql4WbA\nghXyspdSC3e0s6AN9plTGxzysW0Du/a3ly2WA3ycpQO9HWyxepl8AblYfUTRm5lb\ngX9q6JYbGQvkZCd1ejEmhpIZfiwXZsBo1dygCgjlBfIXfLgfAfQATLYOuubdAWUB\nfQIDAQAB\n-----END PUBLIC KEY-----" "pubkey_pem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1knnta8kCSClaIPECAGZ\npD75MIRVD20Ucc/SQP3BFHVCoBhwLt77V3ORpwYph8Wzk9QNYjwXwme8Dd8CCdu1\noLKXbneUn3gR1f/yu2ghih64Qs7DRbIVCILDUmO3PCCePB811Dz5cBABjbUg64p3\nOJbJDtbWxcZYYd5GH3VOo0yhk7RKSZxGNzCnwtzRvhKzdl0hI5F8POA6rkql4WbA\nghXyspdSC3e0s6AN9plTGxzysW0Du/a3ly2WA3ycpQO9HWyxepl8AblYfUTRm5lb\ngX9q6JYbGQvkZCd1ejEmhpIZfiwXZsBo1dygCgjlBfIXfLgfAfQATLYOuubdAWUB\nfQIDAQAB\n-----END PUBLIC KEY-----"
} }
``` ```
## `POST /api/json/token/sign`
Signs submitted blinded tokens with the servers private key. The submitted key needs to hold a charge for each token or the request will fail.
The Key will be discharged by this action.
You cannot submit more than 10 tokens to be signed.
### Parameters
```json
{
"key": <KEY_TO_BE_DISCHARGED>,
"date": <DATE_AS_SUPPLIED_IN_TOKEN_PUBKEY>,
"blinded_tokens": [
"<BLINDED_TOKEN_BIGINT_AS_STRING>",
...
]
}
```
### Example Response
If all blinded tokens were signed successfully response code will be `201`.
If the key isn't charged enough for the amount of tokens or if the date supplied is not valid response code will be `422`
```json
{
"key": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"discharged": <AMOUNT_THAT_WAS_DISCHARGED>,
"date": <DATE_AS_SUPPLIED_IN_TOKEN_PUBKEY>,
"signed_tokens": {
"<BLINDED_TOKEN_BIGINT_AS_STRING>": "<SIGNATURE_BIGINT_AS_STRING>",
...
}
}
```
...@@ -60,8 +60,8 @@ class Crypto { ...@@ -60,8 +60,8 @@ class Crypto {
// Store the key in cache // Store the key in cache
await redis_client await redis_client
.pipeline() .pipeline()
.set(cache_key, 600, private_key.exportKey("pkcs8")) .set(cache_key, private_key.exportKey("pkcs8"))
.expireat(date.add(2, "month").unix()) .expireat(cache_key, date.add(2, "month").unix())
.exec(); .exec();
} else { } else {
let private_key_data = await redis_client.get(cache_key); let private_key_data = await redis_client.get(cache_key);
...@@ -70,6 +70,19 @@ class Crypto { ...@@ -70,6 +70,19 @@ class Crypto {
return private_key; return private_key;
} }
/**
*
* @param {String} blinded_token
* @param {NodeRSA} private_key
* @returns {BigInteger}
*/
sign(blinded_token, private_key) {
return BlindSignature.sign({
blinded: new BigInteger(blinded_token),
key: private_key
});
}
async validateMetaGerPassCode( async validateMetaGerPassCode(
generation_month, generation_month,
expiration_month, expiration_month,
...@@ -116,20 +129,7 @@ class Crypto { ...@@ -116,20 +129,7 @@ class Crypto {
} }
} }
async sign(encrypted_sales_receipts, order_month, expiration_month) {
let private_key = await this.private_key_get(order_month, expiration_month);
let signed_encrypted_sales_receipts = [];
for (let i = 0; i < encrypted_sales_receipts.length; i++) {
signed_encrypted_sales_receipts.push(
BlindSignature.sign({
blinded: new BigInteger(encrypted_sales_receipts[i]),
key: private_key,
}).toString()
);
}
return signed_encrypted_sales_receipts;
}
/** /**
* Creates an hmac hash for purchase data so we can check it later * Creates an hmac hash for purchase data so we can check it later
......
var express = require("express"); var express = require("express");
var router = express.Router(); var router = express.Router();
const {
body,
validationResult
} = require("express-validator");
const config = require("config"); const config = require("config");
const Key = require("../app/Key"); const Key = require("../app/Key");
const Order = require("../app/Order"); const Order = require("../app/Order");
...@@ -182,6 +187,64 @@ router.get("/token/pubkey", async (req, res) => { ...@@ -182,6 +187,64 @@ router.get("/token/pubkey", async (req, res) => {
}); });
}); });
router.post("/token/sign", body("key").notEmpty(), body("date").notEmpty().custom(value => {
// Make sure the date is either for the last month or this month
let date = dayjs(value, config.get("crypto.private_key.date_format"));
let min = dayjs().millisecond(0).second(0).minute(0).hour(0).date(1).subtract(1, "month");
let max = min.add(2, "month");
if (!date.isValid() || date.isBefore(min) || !date.isBefore(max)) {
return Promise.reject("Submitted Date format is invalid");
}
return true;
}),
body("blinded_tokens").notEmpty().withMessage("Blinded Tokens need to be defined")
.isArray({ min: 1, max: 10 }).withMessage("You can supply between 1 and 10 tokens to sign")
.custom(value => {
let checked_tokens = {};
for (let i = 0; i < value.length; i++) {
if (value[i] in checked_tokens) {
return Promise.reject("The supplied tokens need to be unique");
} else {
checked_tokens[value[i]] = true;
}
}
return true;
})
, async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(422).json(errors);
return;
}
let key = await Key.GET_KEY(req.body.key, false);
let date = dayjs(req.body.date, config.get("crypto.private_key.date_format"));
let blinded_tokens = req.body.blinded_tokens;
let signed_tokens = {};
let crypto = new Crypto();
crypto.get_private_key(date).then(private_key => {
for (let i = 0; i < blinded_tokens.length; i++) {
let blinded_token = blinded_tokens[i];
signed_tokens[blinded_token] = crypto.sign(blinded_token, private_key).toString();
}
res.status(201).json({
key: key.get_key,
discharged: blinded_tokens.length,
date: date.format(config.get("crypto.private_key.date_format")),
signed_tokens: signed_tokens
});
}).catch(reason => {
console.error(reason);
res.status(500).json({
status: 500,
message: "Couldn't load private key"
});
});
});
router.use((req, res) => { router.use((req, res) => {
res.status(404).json({ res.status(404).json({
code: 404, code: 404,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment