We want to use key agreement feature of DLMS COSEM to exchange new keys with the meter. In this type we need to use ephermal key pair(for public key ) and a signing key pair(for private key). How these keys will be generated? Will these be provided to me by the manufacturer or will we randomly generate these?
You can generate those keys with the framework. It was a little surprise that Java does not support it.
There is an example how to generate certificate on unit test but I'll copy it here:
/*
* Key agreement test.
*/
@Test
public final void keyAgreementTest() throws Exception {
target.getCiphering().setSecurity(Security.AUTHENTICATION_ENCRYPTION);
target.getProposedConformance().add(Conformance.GENERAL_PROTECTION);
// Generate keys for the client.
target.getCiphering().setSigningKeyPair(getClientTestSigningKeyPair());
target.getCiphering()
.setSystemTitle(GXCommon.hexToBytes("4D4D4D0000BC614E"));
target.getCiphering().setRecipientSystemTitle(
GXCommon.hexToBytes("4D4D4D0000000001"));
server = new TestServer(new GXDLMSAssociationLogicalName(),
InterfaceType.WRAPPER);
server.getCiphering()
.setSystemTitle(GXCommon.hexToBytes("4D4D4D0000000001"));
target.getCiphering().setInvocationCounter(0x0123456789012345L);
server.getCiphering().setInvocationCounter(0x0123456789012345L);
GXDLMSClock clock = new GXDLMSClock();
GXDLMSSecuritySetup ss = new GXDLMSSecuritySetup();
server.getItems().add(clock);
server.getItems().add(ss);
server.initialize();
GXReplyData info = new GXReplyData();
byte[] reply = server.handleRequest(target.aarqRequest()[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
target.parseAareResponse(info.getData());
////////////////////////////////////////////////////////////////
// Generate signing keys.
Date from = new Date();
Date to = new Date(from.getTime() + 365L * 24L * 60L * 60L * 1000L);
// Create client certificate for digital signature.
GXx509Certificate certificate =
GXx509Certificate.createSelfSignedCertificate(
target.getCiphering().getSigningKeyPair(), from, to,
target.getCiphering().getSystemTitle(),
"CN=Test, O=Gurux, L=Tampere, C=FI", KeyUsage.forValue(
(KeyUsage.DIGITAL_SIGNATURE.getValue())));
// Send client's digital signature to the server.
reply = server
.handleRequest(ss.importCertificate(target, certificate)[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
////////////////////////////////////////////////////////////////
// Create server certificate and export it.
reply = server.handleRequest(ss.generateKeyPair(target,
CertificateType.DIGITAL_SIGNATURE)[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
// Note! This is not used. We are using signing key pair from Green Book
// C1.
server.getCiphering().setSigningKeyPair(getServerTestSigningKeyPair());
// Send server's digital signature to the server.
reply = server
.handleRequest(ss.importCertificate(target, certificate)[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
/////////////////////////////////////////////////////////////////
// Change security suite 1 after signature is sent to the server.
target.setSecuritySuite(SecuritySuite.ECDH_ECDSA_AES_GCM_128_SHA_256);
reply = server.handleRequest(target.aarqRequest()[0]);
// target.getCiphering().getPublicKeys()
// .add(new GXSimpleEntry<CertificateType, PublicKey>(
// CertificateType.DIGITAL_SIGNATURE,
// cert.getPublicKey()));
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
target.parseAareResponse(info.getData());
// Generate client's Ephemeral keys and send it to the server.
target.getCiphering()
.setEphemeralKeyPair(getClientEphemeralKeyPairC1());
server.getCiphering()
.setEphemeralKeyPair(getServerEphemeralKeyPairC1());
reply = server.handleRequest(
ss.keyAgreement(target, GlobalKeyType.UNICAST_ENCRYPTION)[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
target.getSharedSecret((byte[]) info.getValue(),
certificate.getPublicKey());
// Check shared secret.
byte[] z = GXCommon.hexToBytes(
"C1 CF 8F E7 89 1A EF 36 17 D7 19 07 95 E6 1F E6 C2 4E FC 3C CA 2E 08 46 9B AD 1A 22 5C E6 EA 08");
Key agreement using
Hi,
You can generate those keys with the framework. It was a little surprise that Java does not support it.
There is an example how to generate certificate on unit test but I'll copy it here:
/*
* Key agreement test.
*/
@Test
public final void keyAgreementTest() throws Exception {
target.getCiphering().setSecurity(Security.AUTHENTICATION_ENCRYPTION);
target.getProposedConformance().add(Conformance.GENERAL_PROTECTION);
// Generate keys for the client.
target.getCiphering().setSigningKeyPair(getClientTestSigningKeyPair());
target.getCiphering()
.setSystemTitle(GXCommon.hexToBytes("4D4D4D0000BC614E"));
target.getCiphering().setRecipientSystemTitle(
GXCommon.hexToBytes("4D4D4D0000000001"));
server = new TestServer(new GXDLMSAssociationLogicalName(),
InterfaceType.WRAPPER);
server.getCiphering()
.setSystemTitle(GXCommon.hexToBytes("4D4D4D0000000001"));
target.getCiphering().setInvocationCounter(0x0123456789012345L);
server.getCiphering().setInvocationCounter(0x0123456789012345L);
GXDLMSClock clock = new GXDLMSClock();
GXDLMSSecuritySetup ss = new GXDLMSSecuritySetup();
server.getItems().add(clock);
server.getItems().add(ss);
server.initialize();
GXReplyData info = new GXReplyData();
byte[] reply = server.handleRequest(target.aarqRequest()[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
target.parseAareResponse(info.getData());
////////////////////////////////////////////////////////////////
// Generate signing keys.
Date from = new Date();
Date to = new Date(from.getTime() + 365L * 24L * 60L * 60L * 1000L);
// Create client certificate for digital signature.
GXx509Certificate certificate =
GXx509Certificate.createSelfSignedCertificate(
target.getCiphering().getSigningKeyPair(), from, to,
target.getCiphering().getSystemTitle(),
"CN=Test, O=Gurux, L=Tampere, C=FI", KeyUsage.forValue(
(KeyUsage.DIGITAL_SIGNATURE.getValue())));
// Send client's digital signature to the server.
reply = server
.handleRequest(ss.importCertificate(target, certificate)[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
////////////////////////////////////////////////////////////////
// Create server certificate and export it.
reply = server.handleRequest(ss.generateKeyPair(target,
CertificateType.DIGITAL_SIGNATURE)[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
// Note! This is not used. We are using signing key pair from Green Book
// C1.
server.getCiphering().setSigningKeyPair(getServerTestSigningKeyPair());
reply = server.handleRequest(ss.generateCertificate(target,
CertificateType.DIGITAL_SIGNATURE)[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
GXPkcs10 cert = new GXPkcs10((byte[]) info.getValue());
certificate = GXx509Certificate.createSelfSignedCertificate(
server.getCiphering().getSigningKeyPair(), from, to,
cert.getSubject(), "CN=Test, O=Gurux, L=Tampere, C=FI",
KeyUsage.forValue((KeyUsage.DIGITAL_SIGNATURE.getValue())));
// Send server's digital signature to the server.
reply = server
.handleRequest(ss.importCertificate(target, certificate)[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
// Export server's certificate.
reply = server.handleRequest(target.getServerCertificate(ss,
CertificateType.DIGITAL_SIGNATURE)[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
certificate = new GXx509Certificate((byte[]) info.getValue());
// Disconnect.
reply = server.handleRequest(target.disconnectRequest());
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
/////////////////////////////////////////////////////////////////
// Change security suite 1 after signature is sent to the server.
target.setSecuritySuite(SecuritySuite.ECDH_ECDSA_AES_GCM_128_SHA_256);
reply = server.handleRequest(target.aarqRequest()[0]);
// target.getCiphering().getPublicKeys()
// .add(new GXSimpleEntry<CertificateType, PublicKey>(
// CertificateType.DIGITAL_SIGNATURE,
// cert.getPublicKey()));
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
target.parseAareResponse(info.getData());
// Generate client's Ephemeral keys and send it to the server.
target.getCiphering()
.setEphemeralKeyPair(getClientEphemeralKeyPairC1());
server.getCiphering()
.setEphemeralKeyPair(getServerEphemeralKeyPairC1());
reply = server.handleRequest(
ss.keyAgreement(target, GlobalKeyType.UNICAST_ENCRYPTION)[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
target.getSharedSecret((byte[]) info.getValue(),
certificate.getPublicKey());
// Check shared secret.
byte[] z = GXCommon.hexToBytes(
"C1 CF 8F E7 89 1A EF 36 17 D7 19 07 95 E6 1F E6 C2 4E FC 3C CA 2E 08 46 9B AD 1A 22 5C E6 EA 08");
// Client generates shared secret.
KeyAgreement ka = KeyAgreement.getInstance("ECDH");
ka.init(target.getCiphering().getEphemeralKeyPair().getPrivate());
ka.doPhase(target.getSettings().getTargetEphemeralKey(), true);
byte[] actual = ka.generateSecret();
assertEquals(GXCommon.toHex(z), GXCommon.toHex(actual));
reply = server.handleRequest(target.read(clock, 2)[0]);
info.clear();
target.getData(reply, info);
assertEquals(0, info.getError());
}
BR,
Mikko