@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()); }