Skip to content

Commit ff8e8d3

Browse files
authored
Ed dsa (#74)
Add an implementation of EdDSA that points to a different implementation. That module should not be required to be loaded.
1 parent 6c2f025 commit ff8e8d3

File tree

11 files changed

+318
-54
lines changed

11 files changed

+318
-54
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11

22
# Mobile Tools for Java (J2ME)
33
.mtj.tmp/
4+
*.gpg
5+
*.asc
46

57
# Package Files #
68
*.jar

nb-configuration.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project-shared-configuration>
3+
<!--
4+
This file contains additional configuration written by modules in the NetBeans IDE.
5+
The configuration is intended to be shared among all the users of project and
6+
therefore it is assumed to be part of version control checkout.
7+
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
8+
-->
9+
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
10+
<!--
11+
Properties that influence various parts of the IDE, especially code formatting and the like.
12+
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
13+
That way multiple projects can share the same settings (useful for formatting rules for example).
14+
Any value defined here will override the pom.xml file value but is only applicable to the current project.
15+
-->
16+
<org-netbeans-modules-javascript2-requirejs.enabled>true</org-netbeans-modules-javascript2-requirejs.enabled>
17+
</properties>
18+
</project-shared-configuration>

nbactions-ossrh.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<actions>
3+
<action>
4+
<actionName>CUSTOM-deploy</actionName>
5+
<displayName>deploy</displayName>
6+
<preAction>build-with-dependencies</preAction>
7+
<goals>
8+
<goal>deploy</goal>
9+
</goals>
10+
<activatedProfiles>
11+
<activatedProfile>ossrh</activatedProfile>
12+
</activatedProfiles>
13+
</action>
14+
</actions>

pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.augustcellars.cose</groupId>
88
<artifactId>cose-java</artifactId>
9-
<version>0.9.7</version>
9+
<version>0.9.8-SNAPSHOT</version>
1010

1111
<name>com.augustcellars.cose:cose-java</name>
1212
<description>A Java implementation that supports the COSE secure message specification.</description>
@@ -136,6 +136,12 @@
136136
</exclusion>
137137
</exclusions>
138138
</dependency>
139+
<dependency>
140+
<groupId>net.i2p.crypto</groupId>
141+
<artifactId>eddsa</artifactId>
142+
<version>0.2.0</version>
143+
<type>jar</type>
144+
</dependency>
139145
</dependencies>
140146

141147
<profiles>

src/main/java/COSE/ASN1.java

Lines changed: 72 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,18 @@ public TagValue(int tagIn, ArrayList<TagValue> listIn) {
4444
// 1.2.840.10045.2.1
4545
public static final byte[] oid_ecPublicKey = new byte[]{0x06, 0x07, 0x2a, (byte) 0x86, 0x48, (byte) 0xce, 0x3d, 0x2, 0x1};
4646

47+
// 1.3.101.110
48+
public static final byte[] Oid_X25519 = new byte[]{0x6, 3, 0x2b, 101, 110};
49+
// 1.3.101.111
50+
public static final byte[] Oid_X448 = new byte[]{0x6, 3, 0x2b, 101, 111};
51+
// 1.3.101.112
52+
public static final byte[] Oid_Ed25519 = new byte[]{0x6, 0x3, 0x2b, 101, 112};
53+
// 1.3.101.113
54+
public static final byte[] Oid_Ed448 = new byte[]{0x6, 0x3, 0x2b, 101, 113};
4755

48-
private static final byte[] SequenceX = new byte[]{0x30};
49-
private static final byte[] BitstringTag = new byte[]{0x3};
50-
private static final byte[] OctetstringTag = new byte[]{0x4};
56+
private static final byte[] SequenceTag = new byte[]{0x30};
57+
private static final byte[] OctetStringTag = new byte[]{0x4};
58+
private static final byte[] BitStringTag = new byte[]{0x3};
5159

5260
/**
5361
* Encode a subject public key info structure from an OID and the data bytes
@@ -58,7 +66,7 @@ public TagValue(int tagIn, ArrayList<TagValue> listIn) {
5866
* @param keyBytes - encoded key bytes
5967
* @return - encoded SPKI
6068
*/
61-
public static byte[] EncodeSubjectPublicKeyInfo(byte[] oid, byte[] keyBytes) throws CoseException
69+
public static byte[] EncodeSubjectPublicKeyInfo(byte[] algorithm, byte[] keyBytes) throws CoseException
6270
{
6371
// SPKI ::= SEQUENCE {
6472
// algorithm SEQUENCE {
@@ -68,9 +76,9 @@ public static byte[] EncodeSubjectPublicKeyInfo(byte[] oid, byte[] keyBytes) thr
6876
// subjectPublicKey BIT STRING CONTAINS key bytes
6977
// }
7078
try {
71-
ArrayList<byte[]> xxx = new ArrayList<>();
72-
xxx.add(AlgorithmIdentifier(oid_ecPublicKey, oid));
73-
xxx.add(BitstringTag);
79+
ArrayList<byte[]> xxx = new ArrayList<byte[]>();
80+
xxx.add(algorithm);
81+
xxx.add(new byte[]{3});
7482
xxx.add(ComputeLength(keyBytes.length+1));
7583
xxx.add(new byte[]{0});
7684
xxx.add(keyBytes);
@@ -84,6 +92,44 @@ public static byte[] EncodeSubjectPublicKeyInfo(byte[] oid, byte[] keyBytes) thr
8492
}
8593

8694
/**
95+
* Encode an EC Private key
96+
* @param oid - curve to use
97+
* @param keyBytes - bytes of the key
98+
* @param spki - optional SPKI
99+
* @return
100+
* @throws CoseException
101+
*/
102+
public static byte[] EncodeEcPrivateKey(byte[] oid, byte[] keyBytes, byte[] spki) throws CoseException
103+
{
104+
// ECPrivateKey ::= SEQUENCE {
105+
// version INTEGER {1}
106+
// privateKey OCTET STRING
107+
// parameters [0] OBJECT IDENTIFIER = named curve
108+
// public key [1] BIT STRING OPTIONAL
109+
// }
110+
//
111+
112+
ArrayList<byte[]> xxx = new ArrayList<byte[]>();
113+
xxx.add(new byte[]{2, 1, 1});
114+
xxx.add(OctetStringTag);
115+
xxx.add(ComputeLength(keyBytes.length));
116+
xxx.add(keyBytes);
117+
xxx.add(new byte[]{(byte)0xa0});
118+
xxx.add(ComputeLength(oid.length));
119+
xxx.add(oid);
120+
if (spki != null) {
121+
xxx.add(new byte[]{(byte)0xa1});
122+
xxx.add(ComputeLength(spki.length+1));
123+
xxx.add(new byte[]{0});
124+
xxx.add(spki);
125+
}
126+
127+
byte[] ecPrivateKey = Sequence(xxx);
128+
129+
return ecPrivateKey;
130+
}
131+
132+
/*
87133
* Decode an object which is supposed to be a SubjectPublicKeyInfo strucuture
88134
* and check that the right set of fields are in the right place
89135
*
@@ -174,15 +220,8 @@ public static TagValue DecodeCompound(int offset, byte[] encoding) throws CoseEx
174220
* @return byte array of encoded bytes
175221
* @throws CoseException
176222
*/
177-
public static byte[] EncodePKCS8(byte[] oid, byte[] keyBytes, byte[] spki) throws CoseException
223+
public static byte[] EncodePKCS8(byte[] algorithm, byte[] keyBytes, byte[] spki) throws CoseException
178224
{
179-
// ECPrivateKey ::= SEQUENCE {
180-
// version INTEGER {1}
181-
// privateKey OCTET STRING
182-
// parameters [0] OBJECT IDENTIFIER = named curve
183-
// public key [1] BIT STRING OPTIONAL
184-
// }
185-
//
186225
// PKCS#8 ::= SEQUENCE {
187226
// version INTEGER {0}
188227
// privateKeyALgorithm SEQUENCE {
@@ -195,29 +234,13 @@ public static byte[] EncodePKCS8(byte[] oid, byte[] keyBytes, byte[] spki) throw
195234
// }
196235

197236
try {
198-
ArrayList<byte[]> xxx = new ArrayList<byte[]>();
199-
xxx.add(new byte[]{2, 1, 1});
200-
xxx.add(OctetstringTag);
201-
xxx.add(ComputeLength(keyBytes.length));
202-
xxx.add(keyBytes);
203-
xxx.add(new byte[]{(byte)0xa0});
204-
xxx.add(ComputeLength(oid.length));
205-
xxx.add(oid);
206-
if (spki != null) {
207-
xxx.add(new byte[]{(byte)0xa1});
208-
xxx.add(ComputeLength(spki.length+1));
209-
xxx.add(new byte[]{0});
210-
xxx.add(spki);
211-
}
212-
213-
byte[] ecPrivateKey = Sequence(xxx);
214237

215-
xxx = new ArrayList<byte[]>();
238+
ArrayList<byte[]> xxx = new ArrayList<byte[]>();
216239
xxx.add(new byte[]{2, 1, 0});
217-
xxx.add(AlgorithmIdentifier(oid_ecPublicKey, oid));
218-
xxx.add(OctetstringTag);
219-
xxx.add(ComputeLength(ecPrivateKey.length));
220-
xxx.add(ecPrivateKey);
240+
xxx.add(algorithm);
241+
xxx.add(OctetStringTag);
242+
xxx.add(ComputeLength(keyBytes.length));
243+
xxx.add(keyBytes);
221244

222245
return Sequence(xxx);
223246
}
@@ -294,7 +317,6 @@ public static ArrayList<TagValue> DecodePKCS8(byte[] encodedData) throws CoseExc
294317
return retValue;
295318
}
296319

297-
298320
public static byte[] EncodeSignature(byte[] r, byte[] s) throws CoseException {
299321
ArrayList<byte[]> x = new ArrayList<byte[]>();
300322
x.add(UnsignedInteger(r));
@@ -303,7 +325,16 @@ public static byte[] EncodeSignature(byte[] r, byte[] s) throws CoseException {
303325
return Sequence(x);
304326
}
305327

306-
private static byte[] AlgorithmIdentifier(byte[] oid, byte[] params) throws CoseException
328+
public static byte[] EncodeOctetString(byte[] data) throws CoseException {
329+
ArrayList<byte[]> x = new ArrayList<byte[]>();
330+
x.add(OctetStringTag);
331+
x.add(ComputeLength(data.length));
332+
x.add(data);
333+
334+
return ToBytes(x);
335+
}
336+
337+
public static byte[] AlgorithmIdentifier(byte[] oid, byte[] params) throws CoseException
307338
{
308339
ArrayList<byte[]> xxx = new ArrayList<byte[]>();
309340
xxx.add(oid);
@@ -312,16 +343,18 @@ private static byte[] AlgorithmIdentifier(byte[] oid, byte[] params) throws Cose
312343
}
313344
return Sequence(xxx);
314345
}
346+
315347
private static byte[] Sequence(ArrayList<byte[]> members) throws CoseException
316348
{
317349
byte[] y = ToBytes(members);
318350
ArrayList<byte[]> x = new ArrayList<byte[]>();
319-
x.add(SequenceX);
351+
x.add(SequenceTag);
320352
x.add(ComputeLength(y.length));
321353
x.add(y);
322354

323355
return ToBytes(x);
324356
}
357+
325358
private static byte[] UnsignedInteger(byte[] i) throws CoseException {
326359
int pad = 0, offset = 0;
327360

src/main/java/COSE/AlgorithmID.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public enum AlgorithmID {
4343
HKDF_HMAC_AES_256(-13, 256, 0),
4444
ECDSA_384(-35, 0, 0),
4545
ECDSA_512(-36, 0, 0),
46+
EDDSA(-8, 0, 0),
4647

4748
ECDH_ES_HKDF_256(-25, 0, 0),
4849
ECDH_ES_HKDF_512(-26, 0, 0),

src/main/java/COSE/KeyKeys.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,26 @@ public enum KeyKeys {
2222
EC2_X(-2),
2323
EC2_Y(-3),
2424
EC2_D(-4),
25+
OKP_Curve(-1),
26+
OKP_X(-2),
27+
OKP_D(-4),
2528
;
2629

2730
private final CBORObject value;
2831

32+
public final static CBORObject KeyType_OKP = CBORObject.FromObject(1);
2933
public final static CBORObject KeyType_EC2 = CBORObject.FromObject(2);
3034
public final static CBORObject KeyType_Octet = CBORObject.FromObject(4);
3135

3236
public final static CBORObject EC2_P256 = CBORObject.FromObject(1);
3337
public final static CBORObject EC2_P384 = CBORObject.FromObject(2);
3438
public final static CBORObject EC2_P521 = CBORObject.FromObject(3);
3539

40+
public final static CBORObject OKP_X25519 = CBORObject.FromObject(4);
41+
public final static CBORObject OKP_X448 = CBORObject.FromObject(5);
42+
public final static CBORObject OKP_Ed25519 = CBORObject.FromObject(6);
43+
public final static CBORObject OKP_Ed448 = CBORObject.FromObject(7);
44+
3645
KeyKeys(int val) {
3746
this.value = CBORObject.FromObject(val);
3847
}

0 commit comments

Comments
 (0)