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