Skip to content

Commit 371f2e7

Browse files
committed
Start implementing signing.
1 parent d45636f commit 371f2e7

File tree

8 files changed

+231
-99
lines changed

8 files changed

+231
-99
lines changed

src/net/sharksystem/asap/protocol/ASAP_Modem_Impl.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public void interest(CharSequence sender, CharSequence recipient, CharSequence f
8181
cryptoSession.sendCmd();
8282

8383
InterestPDU_Impl.sendPDUWithoutCmd(sender, recipient, format, channel, eraFrom, eraTo,
84-
cryptoSession.getOutputStream());
84+
cryptoSession.getOutputStream(), signed);
8585

8686
// finish crypto session - if any
8787
cryptoSession.finish();
@@ -124,7 +124,7 @@ public ASAP_PDU_1_0 readPDU(InputStream is) throws IOException, ASAPException {
124124

125125
int flagsInt = PDU_Impl.readByte(is);
126126

127-
ASAP_PDU_1_0 pdu = null;
127+
PDU_Impl pdu = null;
128128

129129
switch(cmd) {
130130
case ASAP_1_0.OFFER_CMD: pdu = new OfferPDU_Impl(flagsInt, encrypted, is); break;
@@ -133,6 +133,27 @@ public ASAP_PDU_1_0 readPDU(InputStream is) throws IOException, ASAPException {
133133
default: throw new ASAPException("unknown command: " + cmd);
134134
}
135135

136+
if(pdu.signed()) {
137+
String sender = pdu.getSender();
138+
if(sender != null) {
139+
// read signature and try to verify
140+
try {
141+
CryptoSession cryptoSession = new CryptoSession(this.signAndEncryptionKeyStorage);
142+
if(cryptoSession.verify(sender, is)) {
143+
pdu.setVerified(true);
144+
}
145+
}
146+
catch(ASAPException e) {
147+
System.out.println(this.getLogStart() + " cannot verify message");
148+
}
149+
}
150+
}
151+
136152
return pdu;
137153
}
154+
155+
private String getLogStart() {
156+
return this.getClass().getSimpleName() + ": ";
157+
}
158+
138159
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package net.sharksystem.asap.protocol;
2+
3+
interface ASAP_PDU_Management {
4+
void setVerified(boolean b);
5+
}

src/net/sharksystem/asap/protocol/CryptoSession.java

Lines changed: 106 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@
99
import javax.crypto.IllegalBlockSizeException;
1010
import javax.crypto.NoSuchPaddingException;
1111
import java.io.*;
12-
import java.security.InvalidKeyException;
13-
import java.security.NoSuchAlgorithmException;
14-
import java.security.PrivateKey;
15-
import java.security.PublicKey;
12+
import java.security.*;
1613

1714
class CryptoSession {
15+
private Signature signature;
1816
private CharSequence recipient;
1917
private ASAPReadonlyKeyStorage keyStorage;
2018
private Cipher cipher = null;
@@ -24,38 +22,11 @@ class CryptoSession {
2422
private OutputStream effectivOS;
2523
private OutputStream realOS;
2624
private ByteArrayOutputStream asapMessageOS;
27-
private byte[] asapMessageAsBytes;
2825

2926
CryptoSession(ASAPReadonlyKeyStorage keyStorage) {
3027
this.keyStorage = keyStorage;
3128
}
3229

33-
InputStream decrypt(InputStream is) throws ASAPSecurityException {
34-
return this.decrypt(is, this.keyStorage.getPrivateKey());
35-
}
36-
37-
private InputStream decrypt(InputStream is, PrivateKey privateKey) throws ASAPSecurityException {
38-
try {
39-
this.cipher = Cipher.getInstance(keyStorage.getRSAEncryptionAlgorithm());
40-
this.cipher.init(Cipher.DECRYPT_MODE, privateKey);
41-
42-
// read len
43-
int len = PDU_Impl.readIntegerParameter(is);
44-
byte[] messageBytes = new byte[len];
45-
46-
// read encrypted bytes from stream
47-
is.read(messageBytes);
48-
49-
// debugging
50-
// decrypt
51-
byte[] decryptedBytes = this.cipher.doFinal(messageBytes);
52-
return new ByteArrayInputStream(decryptedBytes);
53-
} catch (BadPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException |
54-
NoSuchPaddingException | InvalidKeyException | IOException | ASAPException e) {
55-
throw new ASAPSecurityException(this.getLogStart(), e);
56-
}
57-
}
58-
5930
CryptoSession(byte cmd, OutputStream os, boolean sign, boolean encrypted,
6031
CharSequence recipient,
6132
ASAPReadonlyKeyStorage keyStorage)
@@ -93,13 +64,9 @@ private InputStream decrypt(InputStream is, PrivateKey privateKey) throws ASAPSe
9364
}
9465

9566
// cipher is ready - we can encrypt
96-
this.asapMessageOS = new ByteArrayOutputStream();
97-
// pud will make a detour
98-
this.effectivOS = this.asapMessageOS;
67+
this.setupTempMessageStorage();
9968
}
10069

101-
102-
/*
10370
if(sign) {
10471
// there must be a keyStorage
10572
if(keyStorage == null) {
@@ -113,32 +80,26 @@ private InputStream decrypt(InputStream is, PrivateKey privateKey) throws ASAPSe
11380
}
11481

11582
// ok, we can sign
116-
if(sign) {
117-
// anything was written into a bytearray
11883

11984
// produce signature
120-
Signature signature = null;
12185
try {
122-
signature = Signature.getInstance("TODO_signing_algorithm");
123-
signature.initSign(keyStorage.getPrivateKey()); // desperate try
124-
byte[] bytes2Sign = bufferOS.toByteArray();
125-
signature.update(bytes2Sign);
126-
byte[] signatureBytes = signature.sign();
86+
this.signature = Signature.getInstance(this.keyStorage.getRSASigningAlgorithm());
12787

128-
// send out anything, including signature
88+
// we could sign
89+
this.setupTempMessageStorage();
12990

130-
// TODO need number of bytes payload to find signature later.
131-
os.write(bytes2Sign);
132-
os.write(signatureBytes);
133-
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
91+
} catch (NoSuchAlgorithmException e) {
13492
throw new ASAPSecurityException(e.getLocalizedMessage());
13593
}
13694
}
137-
}
138-
139-
*/
140-
95+
}
14196

97+
private void setupTempMessageStorage() {
98+
if(this.asapMessageOS == null) {
99+
this.asapMessageOS = new ByteArrayOutputStream();
100+
// pud will make a detour
101+
this.effectivOS = this.asapMessageOS;
102+
}
142103
}
143104

144105
public void sendCmd() throws IOException {
@@ -154,42 +115,111 @@ OutputStream getOutputStream() {
154115
return this.effectivOS;
155116
}
156117

118+
private void writeByteArray(byte[] bytes2Write, OutputStream os) throws IOException {
119+
PDU_Impl.sendNonNegativeIntegerParameter(bytes2Write.length, os);
120+
os.write(bytes2Write);
121+
}
122+
123+
private byte[] readByteArray(InputStream is) throws IOException, ASAPException {
124+
// read len
125+
int len = PDU_Impl.readIntegerParameter(is);
126+
byte[] messageBytes = new byte[len];
127+
128+
// read encrypted bytes from stream
129+
is.read(messageBytes);
130+
131+
return messageBytes;
132+
}
133+
157134
public void finish() throws ASAPSecurityException {
158-
if(cipher != null) {
159-
// that is our asap message in clear text
160-
this.asapMessageAsBytes = this.asapMessageOS.toByteArray();
135+
// signing must come first
136+
if(this.signature != null) {
137+
try {
138+
byte[] asapMessageAsBytes = this.asapMessageOS.toByteArray();
139+
this.signature.initSign(this.keyStorage.getPrivateKey());
140+
this.signature.update(asapMessageAsBytes);
141+
byte[] signatureBytes = signature.sign();
142+
143+
if(this.cipher != null) {
144+
// have to store it - anything will be encrypted
145+
this.writeByteArray(signatureBytes, this.asapMessageOS);
146+
} else {
147+
// can write anything now
148+
this.realOS.write(asapMessageAsBytes);
149+
this.writeByteArray(signatureBytes, this.realOS);
150+
}
151+
} catch (InvalidKeyException | SignatureException | IOException e) {
152+
throw new ASAPSecurityException(this.getLogStart(), e);
153+
}
154+
}
155+
156+
if(this.cipher != null) {
161157
try {
162158
// encrypted asap message
163-
byte[] encryptedBytes = this.cipher.doFinal(this.asapMessageAsBytes);
164-
//this.debuggingRememberEncryptedASAPMessage = encryptedBytes;
159+
byte[] asapMessageAsBytes = this.asapMessageOS.toByteArray();
160+
byte[] encryptedBytes = this.cipher.doFinal(asapMessageAsBytes);
165161

166-
// write len
167-
PDU_Impl.sendNonNegativeIntegerParameter(encryptedBytes.length, this.realOS);
168-
// write data
162+
this.writeByteArray(encryptedBytes, this.realOS);
169163
this.realOS.write(encryptedBytes);
164+
} catch (IllegalBlockSizeException | BadPaddingException | IOException e) {
165+
throw new ASAPSecurityException(this.getLogStart(), e);
166+
}
167+
}
168+
}
170169

171-
/*
172-
// debugging - decrypt
170+
////////////////////////////////// verify
173171

174-
// make a test
175-
ByteArrayOutputStream senderSiteTest = new ByteArrayOutputStream();
176-
PDU_Impl.sendNonNegativeIntegerParameter(encryptedBytes.length, senderSiteTest);
177-
senderSiteTest.write(encryptedBytes);
172+
public boolean verify(String sender, InputStream is) throws IOException, ASAPException {
173+
// try to get senders' public key
174+
PublicKey publicKey = this.keyStorage.getPublicKey(sender);
175+
if(publicKey == null) return false;
178176

179-
this.debuggingEncryptedASAPMessageWithLen = senderSiteTest.toByteArray();
177+
try {
178+
this.signature = Signature.getInstance(this.keyStorage.getRSASigningAlgorithm());
179+
this.signature.initVerify(publicKey);
180+
byte[] signatureBytes = this.readByteArray(is);
181+
boolean wasVerified = this.signature.verify(signatureBytes);
182+
return wasVerified;
183+
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
184+
throw new ASAPSecurityException(this.getLogStart(), e);
185+
}
186+
}
180187

181-
PrivateKey privateKey = this.keyStorage.getPrivateKey(this.recipient);
182-
// ByteArrayInputStream decrypt = (ByteArrayInputStream) this.decrypt(new ByteArrayInputStream(senderSiteTest.toByteArray()), privateKey);
183-
ByteArrayInputStream decrypt = (ByteArrayInputStream) this.decrypt(new ByteArrayInputStream(this.debuggingEncryptedASAPMessageWithLen), privateKey);
184-
int i = 42;
185-
*/
186-
} catch (IllegalBlockSizeException | BadPaddingException | IOException e) {
187-
throw new ASAPSecurityException(this.getLogStart(), e);
188-
}
188+
////////////////////////////////// decrypt
189+
190+
InputStream decrypt(InputStream is) throws ASAPSecurityException {
191+
return this.decrypt(is, this.keyStorage.getPrivateKey());
192+
}
193+
194+
// parameter private key is usually no option. There is just one - burt was good for debugging
195+
private InputStream decrypt(InputStream is, PrivateKey privateKey) throws ASAPSecurityException {
196+
try {
197+
this.cipher = Cipher.getInstance(keyStorage.getRSAEncryptionAlgorithm());
198+
this.cipher.init(Cipher.DECRYPT_MODE, privateKey);
199+
200+
// read encrypted message
201+
byte[] messageBytes = this.readByteArray(is);
202+
203+
/*
204+
// read len
205+
int len = PDU_Impl.readIntegerParameter(is);
206+
byte[] messageBytes = new byte[len];
207+
208+
// read encrypted bytes from stream
209+
is.read(messageBytes);
210+
*/
211+
212+
// decrypt
213+
byte[] decryptedBytes = this.cipher.doFinal(messageBytes);
214+
return new ByteArrayInputStream(decryptedBytes);
215+
} catch (BadPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException |
216+
NoSuchPaddingException | InvalidKeyException | IOException | ASAPException e) {
217+
throw new ASAPSecurityException(this.getLogStart(), e);
189218
}
190219
}
191220

192221
private String getLogStart() {
193222
return this.getClass().getSimpleName() + ": ";
194223
}
224+
195225
}

src/net/sharksystem/asap/protocol/InterestPDU_Impl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ private void readFromEra(InputStream is) throws IOException, ASAPException {
3232
}
3333

3434
static void sendPDUWithoutCmd(CharSequence sender, CharSequence recipient, CharSequence format,
35-
CharSequence channel, int eraFrom, int eraTo, OutputStream os)
35+
CharSequence channel, int eraFrom, int eraTo, OutputStream os,
36+
boolean signed)
3637
throws IOException, ASAPException {
3738

3839
if(format == null || format.length() < 1) format = ASAP_1_0.ANY_FORMAT;
@@ -50,6 +51,7 @@ static void sendPDUWithoutCmd(CharSequence sender, CharSequence recipient, CharS
5051
flags = PDU_Impl.setFlag(channel, flags, CHANNEL_BIT_POSITION);
5152
flags = PDU_Impl.setFlag(eraFrom, flags, ERA_FROM_BIT_POSITION);
5253
flags = PDU_Impl.setFlag(eraTo, flags, ERA_TO_BIT_POSITION);
54+
flags = PDU_Impl.setFlag(signed, flags, SIGNED_TO_BIT_POSITION);
5355

5456
PDU_Impl.sendFlags(flags, os);
5557

src/net/sharksystem/asap/protocol/PDU_Impl.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@
1010

1111
import static net.sharksystem.asap.protocol.ASAP_1_0.ERA_NOT_DEFINED;
1212

13-
abstract class PDU_Impl implements ASAP_PDU_1_0 {
13+
abstract class PDU_Impl implements ASAP_PDU_1_0, ASAP_PDU_Management {
1414
public static final int SENDER_BIT_POSITION = 0;
1515
public static final int RECIPIENT_PEER_BIT_POSITION = 1;
1616
public static final int CHANNEL_BIT_POSITION = 2;
1717
public static final int ERA_BIT_POSITION = 3;
1818
public static final int ERA_FROM_BIT_POSITION = 4;
1919
public static final int ERA_TO_BIT_POSITION = 5;
2020
public static final int OFFSETS_BIT_POSITION = 6;
21+
public static final int SIGNED_TO_BIT_POSITION = 7;
2122

2223
private boolean senderSet = false;
2324
private boolean recipientSet = false;
@@ -48,6 +49,10 @@ abstract class PDU_Impl implements ASAP_PDU_1_0 {
4849
public boolean signed() { return this.signed; }
4950
public boolean verified() { return this.verified; };
5051

52+
public void setVerified(boolean verified) {
53+
this.verified = verified;
54+
}
55+
5156
public String toString() {
5257
StringBuilder sb = new StringBuilder();
5358

@@ -61,10 +66,18 @@ public String toString() {
6166
sb.append(" | format: "); sb.append(format);
6267
sb.append(" | channel: "); if(channelSet) sb.append(this.channel); else sb.append("not set");
6368
sb.append(" | era: "); if(eraSet) sb.append(era); else sb.append("not set");
69+
sb.append(" | signed: "); this.appendTrueFalse(this.signed, sb);
70+
sb.append(" | verified: "); this.appendTrueFalse(this.verified, sb);
71+
sb.append(" | encrypted: "); this.appendTrueFalse(this.encrypted, sb);
6472

6573
return sb.toString();
6674
}
6775

76+
private void appendTrueFalse(boolean value, StringBuilder sb) {
77+
if(value) sb.append("true");
78+
else sb.append("false");
79+
}
80+
6881
/**
6982
* @param cmd
7083
* @param flags
@@ -127,6 +140,12 @@ protected void evaluateFlags(int flag) {
127140
testFlag = testFlag << OFFSETS_BIT_POSITION;
128141
result = flag & testFlag;
129142
offsetsSet = result != 0;
143+
144+
// signed parameter set ?
145+
testFlag = 1;
146+
testFlag = testFlag << SIGNED_TO_BIT_POSITION;
147+
result = flag & testFlag;
148+
this.signed = result != 0;
130149
}
131150

132151
@Override
@@ -308,6 +327,17 @@ static int setFlag(int parameter, int flags, int bit_position) {
308327
return flags;
309328
}
310329

330+
static int setFlag(boolean parameter, int flags, int bit_position) {
331+
if(parameter) {
332+
int newFlag = 1;
333+
newFlag = newFlag << bit_position;
334+
335+
return flags | newFlag;
336+
}
337+
338+
return flags;
339+
}
340+
311341
static void checkValidStream(OutputStream os) throws ASAPException {
312342
if(os == null) throw new ASAPException("outputstream must not be null");
313343
}

0 commit comments

Comments
 (0)