/* * Copyright 2015 Kevin Herron * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.digitalpetri.opcua.stack.core.channel.headers; import java.nio.charset.Charset; import javax.annotation.Nonnull; import com.digitalpetri.opcua.stack.core.types.builtin.ByteString; import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; import io.netty.buffer.ByteBuf; public class AsymmetricSecurityHeader { private final String securityPolicyUri; private final ByteString senderCertificate; private final ByteString receiverThumbprint; /** * @param securityPolicyUri the URI of the Security Policy used to secure the Message. * @param senderCertificate the DER-encoded X509v3 Certificate assigned to the sending Application * Instance. This field shall be null if the Message is not signed. * @param receiverThumbprint the thumbprint of the X509v3 Certificate assigned to the receiving Application * Instance. The thumbprint is the SHA1 digest of the DER encoded form of the * Certificate. This indicates what public key was used to encrypt the MessageChunk. This * field shall be null if the Message is not encrypted. */ public AsymmetricSecurityHeader(@Nonnull String securityPolicyUri, @Nonnull ByteString senderCertificate, @Nonnull ByteString receiverThumbprint) { Preconditions.checkNotNull(securityPolicyUri); Preconditions.checkArgument(securityPolicyUri.getBytes(Charset.forName("UTF-8")).length <= 255, "securityPolicyUri length cannot be greater than 255 bytes"); Preconditions.checkArgument(receiverThumbprint.bytes() == null || receiverThumbprint.length() == 20, "receiverThumbprint length must be either null or exactly 20 bytes"); this.securityPolicyUri = securityPolicyUri; this.senderCertificate = senderCertificate; this.receiverThumbprint = receiverThumbprint; } @Nonnull public String getSecurityPolicyUri() { return securityPolicyUri; } @Nonnull public ByteString getSenderCertificate() { return senderCertificate; } @Nonnull public ByteString getReceiverThumbprint() { return receiverThumbprint; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AsymmetricSecurityHeader that = (AsymmetricSecurityHeader) o; return receiverThumbprint.equals(that.receiverThumbprint) && securityPolicyUri.equals(that.securityPolicyUri) && senderCertificate.equals(that.senderCertificate); } @Override public int hashCode() { int result = securityPolicyUri.hashCode(); result = 31 * result + senderCertificate.hashCode(); result = 31 * result + receiverThumbprint.hashCode(); return result; } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("securityPolicyUri", securityPolicyUri) .add("senderCertificate", senderCertificate) .add("receiverThumbprint", receiverThumbprint) .toString(); } public static void encode(AsymmetricSecurityHeader header, ByteBuf buffer) { String securityPolicy = header.getSecurityPolicyUri(); buffer.writeInt(securityPolicy.length()); buffer.writeBytes(securityPolicy.getBytes(Charset.forName("UTF-8"))); ByteString senderCertificate = header.getSenderCertificate(); if (senderCertificate.isNull()) { buffer.writeInt(-1); } else { buffer.writeInt(senderCertificate.length()); buffer.writeBytes(senderCertificate.bytes()); } ByteString receiverThumbprint = header.getReceiverThumbprint(); if (receiverThumbprint.isNull()) { buffer.writeInt(-1); } else { buffer.writeInt(receiverThumbprint.length()); buffer.writeBytes(receiverThumbprint.bytes()); } } public static AsymmetricSecurityHeader decode(ByteBuf buffer) { /* SecurityPolicyUri */ int securityPolicyUriLength = buffer.readInt(); String securityPolicyUri = new String( buffer.readBytes(securityPolicyUriLength).array(), Charset.forName("UTF-8") ); /* SenderCertificate */ int senderCertificateLength = buffer.readInt(); byte[] senderCertificate = senderCertificateLength >= 0 ? buffer.readBytes(senderCertificateLength).array() : null; /* ReceiverCertificateThumbprint */ int thumbprintLength = buffer.readInt(); byte[] receiverCertificateThumbprint = thumbprintLength >= 0 ? buffer.readBytes(thumbprintLength).array() : null; return new AsymmetricSecurityHeader( securityPolicyUri, new ByteString(senderCertificate), new ByteString(receiverCertificateThumbprint) ); } }