1 package civitas.bboard.server.controllers;
2
3 import java.security.PublicKey;
4 import java.util.ArrayList;
5 import java.util.Base64;
6 import java.util.List;
7
8 import org.bouncycastle.crypto.CryptoException;
9 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.stereotype.Controller;
11 import org.springframework.web.bind.annotation.PathVariable;
12 import org.springframework.web.bind.annotation.PostMapping;
13
14 import civitas.bboard.server.Board;
15 import civitas.bboard.server.BoardRepository;
16 import civitas.bboard.server.GetBoardForId;
17 import civitas.common.board.BoardClosedContentCommitment;
18 import civitas.common.election.ElectionID;
19 import civitas.crypto.CryptoBase;
20 import civitas.crypto.messagedigest.CryptoHash;
21 import civitas.crypto.rsapublickey.ConvertStringToPublicKey;
22 import civitas.crypto.rsapublickey.VerifyPublicKeySignature;
23 import civitas.crypto.signature.Signature;
24 import jakarta.annotation.Nonnull;
25
26 @Controller
27 public class CloseBoardController {
28
29 @Autowired
30 VerifyPublicKeySignature verifyPublicKeySignature;
31
32 @Autowired
33 BoardRepository boardRepository;
34
35 @Autowired
36 CryptoBase cryptoBase;
37
38 @Autowired
39 CryptoHash cryptoHash;
40
41 @Autowired
42 GetBoardForId getBoardForId;
43
44 @Autowired
45 GetRestTemplate getRestTemplate;
46
47 @Autowired
48 ConvertStringToPublicKey convertStringToPublicKey;
49
50 @PostMapping("/boards/close/{bbid}")
51 public boolean apply(
52 @PathVariable("bbid") final String bbid,
53 @Nonnull final ElectionID postHashTo,
54 final int numVoterBlocks,
55 @Nonnull final Signature sig)
56 throws CommunicableException {
57 if (null == sig) {
58 throw new NullPointerException();
59 }
60 if (numVoterBlocks < 0) {
61 throw new IllegalArgumentException("number of voter blocks is negative");
62 }
63 Board board = getBoardForId.apply(bbid, true);
64 PublicKey key;
65 boolean res;
66 try {
67 key = convertStringToPublicKey.apply(board.keyString);
68 res = verifyPublicKeySignature.apply(sig, key, bbid);
69 } catch (CryptoException e) {
70 throw new CommunicableException("cannot verify signature");
71 }
72 if (res) {
73
74 List<String> hashes = new ArrayList<>();
75 for (int i = 0; i < numVoterBlocks; i++) {
76 String meta = "voterSubmission-voterBlock" + i;
77 hashes.add(Base64.getEncoder().encodeToString(cryptoHash.apply(bbid.getBytes(), meta.getBytes())));
78 }
79 BoardClosedContentCommitment bccc = new BoardClosedContentCommitment(postHashTo, bbid, hashes);
80 String uriBase = postHashTo.uriBase();
81 String uri = uriBase + "/post";
82
83 getRestTemplate.apply().postForObject(uri, bccc, Boolean.class);
84 board.isOpen = false;
85 boardRepository.save(board);
86 }
87 return res;
88 }
89 }