View Javadoc
1   package civitas.bboard.server.controllers;
2   
3   import java.io.IOException;
4   import java.math.BigInteger;
5   import java.security.KeyStoreException;
6   import java.security.NoSuchAlgorithmException;
7   import java.security.PrivateKey;
8   import java.security.PublicKey;
9   import java.security.UnrecoverableKeyException;
10  import java.security.cert.CertificateException;
11  
12  import org.bouncycastle.crypto.CryptoException;
13  import org.slf4j.MarkerFactory;
14  import org.springframework.beans.factory.annotation.Autowired;
15  import org.springframework.stereotype.Controller;
16  import org.springframework.web.bind.annotation.PathVariable;
17  import org.springframework.web.bind.annotation.PostMapping;
18  import org.springframework.web.bind.annotation.RequestBody;
19  import org.springframework.web.bind.annotation.ResponseBody;
20  
21  import civitas.bboard.common.BBPost;
22  import civitas.bboard.common.BBPostRepository;
23  import civitas.bboard.server.GetBoardForId;
24  import civitas.bboard.server.electioncache.UpdateCache;
25  import civitas.common.CheckAccess;
26  import civitas.common.Configuration;
27  import civitas.common.ConvertToXml;
28  import civitas.common.GetPrivateKey;
29  import civitas.common.GetPublicKey;
30  import civitas.common.LoggerService;
31  import civitas.common.Operation;
32  import civitas.crypto.messagedigest.CryptoHash;
33  import civitas.crypto.rsapublickey.VerifyPublicKeySignature;
34  import civitas.crypto.signature.SignWithPublicKey;
35  import civitas.crypto.signature.Signature;
36  import civitas.util.GetCurrentTime;
37  import jakarta.xml.bind.JAXBException;
38  
39  @Controller
40  // @RestController
41  public class PostController {
42  	@Autowired
43  	GetBoardForId getBoardForId;
44  
45  	@Autowired
46  	BBPostRepository bBPostRepository;
47  
48  	@Autowired
49  	CryptoHash cryptoHash;
50  
51  	@Autowired
52  	LoggerService logger;
53  
54  	@Autowired
55  	UpdateCache updateCache;
56  
57  	@Autowired
58  	ConvertToXml convertToXml;
59  
60  	@Autowired
61  	SignWithPublicKey signWithPublicKey;
62  
63  	@Autowired
64  	GetPrivateKey getPrivateKey;
65  
66  	@Autowired
67  	GetPublicKey getPublicKey;
68  
69  	@Autowired
70  	GetCurrentTime getCurrentTime;
71  
72  	@Autowired
73  	VerifyPublicKeySignature verifyPublicKeySignature;
74  
75  	@Autowired
76  	CheckAccess checkAccess;
77  
78  	@Autowired
79  	Configuration configuration;
80  
81  	@PostMapping("/boards/{bbid}")
82  	@ResponseBody
83  	public Long apply(@PathVariable("bbid") final String bbid, @RequestBody final PostDTO dto)
84  			throws CommunicableException {
85  		String objectID = dto.meta() + bbid;
86  		checkAccess.apply(Operation.POST, dto.signature().getSignerPubKey(), objectID);
87  		try {
88  			if (!verifyPublicKeySignature.apply(
89  					dto.signature(), dto.payloadXml().getBytes())) {
90  				throw new CommunicableException("bad signature");
91  			}
92  		} catch (CryptoException e) {
93  			throw new CommunicableException("bad signature (but in blue)");
94  		}
95  
96  		logger.apply(MarkerFactory.getMarker("bbs_post"), objectID);
97  
98  		getBoardForId.apply(bbid, true);
99  
100 		long t = getCurrentTime.apply();
101 
102 		Iterable<BBPost> lastPosts = bBPostRepository.findByBbidOrderBySerialDesc(bbid);
103 
104 		BBPost lastPost = null;
105 		byte[] hash = new byte[0];
106 		if (lastPosts.iterator().hasNext()) {
107 			lastPost = lastPosts.iterator().next();
108 			hash = lastPost.hash;
109 		}
110 		byte[] newhash = cryptoHash.apply(hash, BigInteger.valueOf(t).toByteArray(), dto.signature().signatureBytes);
111 
112 		try {
113 			updateCache.apply(bbid, dto.meta(), dto.payloadXml(), t);
114 		} catch (IOException | JAXBException e) {
115 			throw new CommunicableException("bad payload xml");
116 		}
117 
118 		Long serial = 0L;
119 		if (lastPost != null) {
120 			serial = lastPost.serial;
121 		}
122 		bBPostRepository.save(new BBPost(bbid, serial + 1, t, dto.meta(), dto.payloadXml(), dto.signature(), newhash));
123 
124 		return t;
125 	}
126 
127 	public long apply(final String bbid, final String meta, final Object mesg)
128 			throws JAXBException, UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException,
129 					CertificateException, IOException, CryptoException, CommunicableException {
130 		String msg = convertToXml.apply(mesg);
131 		PrivateKey privKey =
132 				getPrivateKey.apply(configuration.storeFile, configuration.storePassword, configuration.serverKeyEntry);
133 		PublicKey pubKey =
134 				getPublicKey.apply(configuration.storeFile, configuration.storePassword, configuration.serverKeyEntry);
135 		Signature sign = signWithPublicKey.apply(privKey, pubKey, msg.getBytes());
136 		return apply(bbid, new PostDTO(meta, msg, sign));
137 	}
138 }