use of org.eclipse.milo.opcua.stack.core.security.SecurityAlgorithm in project milo by eclipse.
the class AbstractX509IdentityValidator method validateX509Token.
@Override
protected T validateX509Token(Session session, X509IdentityToken token, UserTokenPolicy tokenPolicy, SignatureData tokenSignature) throws UaException {
ByteString clientCertificateBs = token.getCertificateData();
X509Certificate identityCertificate = CertificateUtil.decodeCertificate(clientCertificateBs.bytesOrEmpty());
// verify the algorithm matches the one specified by the tokenPolicy or else the channel itself
if (tokenPolicy.getSecurityPolicyUri() != null) {
SecurityPolicy securityPolicy = SecurityPolicy.fromUri(tokenPolicy.getSecurityPolicyUri());
if (!securityPolicy.getAsymmetricSignatureAlgorithm().getUri().equals(tokenSignature.getAlgorithm())) {
throw new UaException(StatusCodes.Bad_SecurityChecksFailed, "algorithm in token signature did not match algorithm specified by token policy");
}
} else {
SecurityPolicy securityPolicy = session.getSecurityConfiguration().getSecurityPolicy();
if (!securityPolicy.getAsymmetricSignatureAlgorithm().getUri().equals(tokenSignature.getAlgorithm())) {
throw new UaException(StatusCodes.Bad_SecurityChecksFailed, "algorithm in token signature did not match algorithm specified by secure channel");
}
}
SecurityAlgorithm algorithm = SecurityAlgorithm.fromUri(tokenSignature.getAlgorithm());
if (algorithm != SecurityAlgorithm.None) {
verifySignature(session, tokenSignature, identityCertificate, algorithm);
}
return authenticateIdentityCertificateOrThrow(session, identityCertificate);
}
use of org.eclipse.milo.opcua.stack.core.security.SecurityAlgorithm in project milo by eclipse.
the class SessionManager method getServerSignature.
private SignatureData getServerSignature(SecurityPolicy securityPolicy, KeyPair keyPair, ByteString clientNonce, ByteString clientCertificate) throws UaException {
if (securityPolicy == SecurityPolicy.None) {
return new SignatureData(null, null);
} else {
try {
SecurityAlgorithm algorithm = securityPolicy.getAsymmetricSignatureAlgorithm();
byte[] data = Bytes.concat(clientCertificate.bytes(), clientNonce.bytes());
byte[] signature = SignatureUtil.sign(algorithm, keyPair.getPrivate(), ByteBuffer.wrap(data));
return new SignatureData(algorithm.getUri(), ByteString.of(signature));
} catch (UaRuntimeException e) {
throw new UaException(StatusCodes.Bad_SecurityChecksFailed);
}
}
}
use of org.eclipse.milo.opcua.stack.core.security.SecurityAlgorithm in project milo by eclipse.
the class SessionFsmFactory method buildClientSignature.
@SuppressWarnings("Duplicates")
private static SignatureData buildClientSignature(OpcUaClientConfig config, ByteString serverNonce) throws Exception {
EndpointDescription endpoint = config.getEndpoint();
SecurityPolicy securityPolicy = SecurityPolicy.fromUri(endpoint.getSecurityPolicyUri());
if (securityPolicy == SecurityPolicy.None) {
return new SignatureData(null, null);
} else {
SecurityAlgorithm signatureAlgorithm = securityPolicy.getAsymmetricSignatureAlgorithm();
PrivateKey privateKey = config.getKeyPair().map(KeyPair::getPrivate).orElse(null);
List<X509Certificate> serverCertificates = CertificateUtil.decodeCertificates(endpoint.getServerCertificate().bytesOrEmpty());
// Signature data is serverCert + serverNonce signed with our private key.
byte[] serverNonceBytes = serverNonce.bytesOrEmpty();
byte[] serverCertificateBytes = serverCertificates.get(0).getEncoded();
byte[] dataToSign = Bytes.concat(serverCertificateBytes, serverNonceBytes);
byte[] signature = SignatureUtil.sign(signatureAlgorithm, privateKey, ByteBuffer.wrap(dataToSign));
return new SignatureData(signatureAlgorithm.getUri(), ByteString.of(signature));
}
}
use of org.eclipse.milo.opcua.stack.core.security.SecurityAlgorithm in project milo by eclipse.
the class ChannelSecurity method generateKeyPair.
public static SecurityKeys generateKeyPair(SecureChannel channel, ByteString clientNonce, ByteString serverNonce) {
SecurityAlgorithm keyDerivation = channel.getSecurityPolicy().getKeyDerivationAlgorithm();
int signatureKeySize = channel.getSymmetricSignatureKeySize();
int encryptionKeySize = channel.getSymmetricEncryptionKeySize();
int cipherTextBlockSize = channel.getSymmetricBlockSize();
assert (clientNonce != null);
assert (serverNonce != null);
byte[] clientSignatureKey = (keyDerivation == SecurityAlgorithm.PSha1) ? PShaUtil.createPSha1Key(serverNonce.bytes(), clientNonce.bytes(), 0, signatureKeySize) : PShaUtil.createPSha256Key(serverNonce.bytes(), clientNonce.bytes(), 0, signatureKeySize);
byte[] clientEncryptionKey = (keyDerivation == SecurityAlgorithm.PSha1) ? PShaUtil.createPSha1Key(serverNonce.bytes(), clientNonce.bytes(), signatureKeySize, encryptionKeySize) : PShaUtil.createPSha256Key(serverNonce.bytes(), clientNonce.bytes(), signatureKeySize, encryptionKeySize);
byte[] clientInitializationVector = (keyDerivation == SecurityAlgorithm.PSha1) ? PShaUtil.createPSha1Key(serverNonce.bytes(), clientNonce.bytes(), signatureKeySize + encryptionKeySize, cipherTextBlockSize) : PShaUtil.createPSha256Key(serverNonce.bytes(), clientNonce.bytes(), signatureKeySize + encryptionKeySize, cipherTextBlockSize);
byte[] serverSignatureKey = (keyDerivation == SecurityAlgorithm.PSha1) ? PShaUtil.createPSha1Key(clientNonce.bytes(), serverNonce.bytes(), 0, signatureKeySize) : PShaUtil.createPSha256Key(clientNonce.bytes(), serverNonce.bytes(), 0, signatureKeySize);
byte[] serverEncryptionKey = (keyDerivation == SecurityAlgorithm.PSha1) ? PShaUtil.createPSha1Key(clientNonce.bytes(), serverNonce.bytes(), signatureKeySize, encryptionKeySize) : PShaUtil.createPSha256Key(clientNonce.bytes(), serverNonce.bytes(), signatureKeySize, encryptionKeySize);
byte[] serverInitializationVector = (keyDerivation == SecurityAlgorithm.PSha1) ? PShaUtil.createPSha1Key(clientNonce.bytes(), serverNonce.bytes(), signatureKeySize + encryptionKeySize, cipherTextBlockSize) : PShaUtil.createPSha256Key(clientNonce.bytes(), serverNonce.bytes(), signatureKeySize + encryptionKeySize, cipherTextBlockSize);
return new SecurityKeys(new SecretKeys(clientSignatureKey, clientEncryptionKey, clientInitializationVector), new SecretKeys(serverSignatureKey, serverEncryptionKey, serverInitializationVector));
}
use of org.eclipse.milo.opcua.stack.core.security.SecurityAlgorithm in project milo by eclipse.
the class AbstractUsernameIdentityValidator method validateUsernameToken.
@Override
protected T validateUsernameToken(Session session, UserNameIdentityToken token, UserTokenPolicy tokenPolicy, SignatureData tokenSignature) throws UaException {
String username = token.getUserName();
ByteString lastNonce = session.getLastNonce();
int lastNonceLength = lastNonce.length();
if (username == null || username.isEmpty()) {
throw new UaException(StatusCodes.Bad_IdentityTokenInvalid);
}
SecurityAlgorithm algorithm;
String algorithmUri = token.getEncryptionAlgorithm();
if (algorithmUri == null || algorithmUri.isEmpty()) {
SecurityPolicy securityPolicy = session.getSecurityConfiguration().getSecurityPolicy();
algorithm = securityPolicy.getAsymmetricEncryptionAlgorithm();
} else {
try {
algorithm = SecurityAlgorithm.fromUri(algorithmUri);
} catch (UaException e) {
throw new UaException(StatusCodes.Bad_IdentityTokenInvalid);
}
if (algorithm != SecurityAlgorithm.Rsa15 && algorithm != SecurityAlgorithm.RsaOaepSha1 && algorithm != SecurityAlgorithm.RsaOaepSha256) {
throw new UaException(StatusCodes.Bad_IdentityTokenInvalid);
}
}
byte[] tokenBytes = token.getPassword().bytesOrEmpty();
if (algorithm != SecurityAlgorithm.None) {
byte[] plainTextBytes = decryptTokenData(session, algorithm, tokenBytes);
// @formatter:off
long length = ((plainTextBytes[3] & 0xFFL) << 24) | ((plainTextBytes[2] & 0xFFL) << 16) | ((plainTextBytes[1] & 0xFFL) << 8) | (plainTextBytes[0] & 0xFFL);
if (length > plainTextBytes.length - 4) {
throw new UaException(StatusCodes.Bad_IdentityTokenInvalid, "invalid token data");
}
int passwordLength = (int) length - lastNonceLength;
if (passwordLength < 0) {
throw new UaException(StatusCodes.Bad_IdentityTokenInvalid, "invalid password length");
}
if (passwordLength > session.getServer().getConfig().getLimits().getMaxPasswordLength().longValue()) {
throw new UaException(StatusCodes.Bad_EncodingLimitsExceeded, "password length exceeds limits");
}
byte[] passwordBytes = new byte[passwordLength];
byte[] nonceBytes = new byte[lastNonceLength];
System.arraycopy(plainTextBytes, 4, passwordBytes, 0, passwordBytes.length);
System.arraycopy(plainTextBytes, 4 + passwordBytes.length, nonceBytes, 0, lastNonceLength);
if (MessageDigest.isEqual(lastNonce.bytes(), nonceBytes)) {
String password = new String(passwordBytes, StandardCharsets.UTF_8);
return authenticateUsernameOrThrow(session, username, password);
} else {
throw new UaException(StatusCodes.Bad_UserAccessDenied);
}
} else {
String password = new String(tokenBytes, StandardCharsets.UTF_8);
return authenticateUsernameOrThrow(session, username, password);
}
}
Aggregations