public int getCipherTextBlockSize(X509Certificate certificate, SecurityPolicy securityPolicy) { SecurityAlgorithm algorithm = securityPolicy.getAsymmetricEncryptionAlgorithm(); switch (algorithm) { case Rsa15: case RsaOaep: return (getAsymmetricKeyLength(certificate) + 1) / 8; } return 1; }
public Cipher getAndInitializeCipher( X509Certificate serverCertificate, SecurityPolicy securityPolicy) throws UaException { assert (serverCertificate != null); try { String transformation = securityPolicy.getAsymmetricEncryptionAlgorithm().getTransformation(); Cipher cipher = Cipher.getInstance(transformation); cipher.init(Cipher.ENCRYPT_MODE, serverCertificate.getPublicKey()); return cipher; } catch (GeneralSecurityException e) { throw new UaException(StatusCodes.Bad_SecurityChecksFailed, e); } }
@Override public Tuple2<UserIdentityToken, SignatureData> getIdentityToken( EndpointDescription endpoint, ByteString serverNonce) throws Exception { UserTokenPolicy tokenPolicy = Arrays.stream(endpoint.getUserIdentityTokens()) .filter(t -> t.getTokenType() == UserTokenType.UserName) .findFirst() .orElseThrow(() -> new Exception("no username token policy found")); String policyId = tokenPolicy.getPolicyId(); SecurityPolicy securityPolicy = SecurityPolicy.None; String securityPolicyUri = tokenPolicy.getSecurityPolicyUri(); try { if (securityPolicyUri != null && !securityPolicyUri.isEmpty()) { securityPolicy = SecurityPolicy.fromUri(securityPolicyUri); } else { securityPolicyUri = endpoint.getSecurityPolicyUri(); securityPolicy = SecurityPolicy.fromUri(securityPolicyUri); } } catch (Throwable t) { logger.warn( "Error parsing SecurityPolicy for uri={}, falling back to no security.", securityPolicyUri); } byte[] passwordBytes = password.getBytes("UTF-8"); byte[] nonceBytes = Optional.ofNullable(serverNonce.bytes()).orElse(new byte[0]); ByteBuf buffer = Unpooled.buffer().order(ByteOrder.LITTLE_ENDIAN); if (securityPolicy == SecurityPolicy.None) { buffer.writeBytes(passwordBytes); } else { buffer.writeInt(passwordBytes.length + nonceBytes.length); buffer.writeBytes(passwordBytes); buffer.writeBytes(nonceBytes); ByteString bs = endpoint.getServerCertificate(); X509Certificate certificate = CertificateUtil.decodeCertificate(bs.bytes()); int plainTextBlockSize = getPlainTextBlockSize(certificate, securityPolicy); int cipherTextBlockSize = getCipherTextBlockSize(certificate, securityPolicy); int blockCount = (buffer.readableBytes() + plainTextBlockSize - 1) / plainTextBlockSize; Cipher cipher = getAndInitializeCipher(certificate, securityPolicy); ByteBuffer plainTextNioBuffer = buffer.nioBuffer(); ByteBuffer cipherTextNioBuffer = Unpooled.buffer(cipherTextBlockSize * blockCount) .order(ByteOrder.LITTLE_ENDIAN) .nioBuffer(0, cipherTextBlockSize * blockCount); for (int blockNumber = 0; blockNumber < blockCount; blockNumber++) { int position = blockNumber * plainTextBlockSize; int limit = Math.min(buffer.readableBytes(), (blockNumber + 1) * plainTextBlockSize); plainTextNioBuffer.position(position).limit(limit); cipher.doFinal(plainTextNioBuffer, cipherTextNioBuffer); } cipherTextNioBuffer.flip(); buffer = Unpooled.wrappedBuffer(cipherTextNioBuffer); } byte[] bs = new byte[buffer.readableBytes()]; buffer.readBytes(bs); // UA Part 4, Section 7.35.3 UserNameIdentityToken: // encryptionAlgorithm parameter is null if the password is not encrypted. String securityAlgorithmUri = securityPolicy.getAsymmetricEncryptionAlgorithm().getUri(); String encryptionAlgorithm = securityAlgorithmUri.isEmpty() ? null : securityAlgorithmUri; UserNameIdentityToken token = new UserNameIdentityToken(policyId, username, ByteString.of(bs), encryptionAlgorithm); return new Tuple2<>(token, new SignatureData()); }