2016-09-13 36 views
2

クライアントがこの認証パラメータ「証明書+秘密鍵」を持つサーバに接続することは可能ですか? 「セキュリティポリシー」と「メッセージセキュリティモード」のパラメータもありますか?Eclipse Miloの認証クライアント - サーバ

(UAExpertクライアントのように:http://documentation.unified-automation.com/uaexpert/1.4.0/html/connect.html

yesの場合、どのように?


私は私の処分で持っている:

  • ".perm" ファイルフォーマットで1つの秘密鍵。
  • ".der"ファイル形式の証明書。
  • ".der"ファイル形式のサーバーの1つのCA。
  • と ".der"ファイル形式の4096ビットのサーバーのCA。

答えて

1

はい、現時点ではユーザー名/パスワードの使用が「簡単」にはできませんが、現在可能です。

クライアントSDKは、IdentityProviderというインターフェイスを公開しています。このインターフェイスは、クライアントの接続中に委任され、エンドポイントとサーバーノンスが与えられます。これは、UserIdentityTokenSignatureDataを含む2タプルを返します。

X509IdentityTokenケース用にこのインターフェイスを実装し、証明書(X509IdentityToken)を返すだけでなく、鍵を持っていることを証明する必要があります(SignatureData)。

IdentityProviderを取得したら、OpcUaClientConfigオブジェクトをビルドするときにsetIdentityProviderを呼び出して、クライアントに設定する際に使用するようにクライアントに指示するだけです。

これはちょっと面倒ですがSDKのポイントはユーザーに負担を軽減することですので、これもMiloの機能チケットにします。あなたが自分でそれを実装するまでになっていないなら、私は今週それを得ることができます。

+0

そして、ちょうど明確にする:これは、ユーザを認証するためにX509証明書を使用してについてです。クライアントサーバー間の通信を保護するためにクライアントによって使用される証明書を設定するのと同じことではありません。それはもちろん、サポートされています。 –

+0

さて、私は見て、私はメソッドを実装しようとします。 私は私の処分で持っている: - 「.perm」ファイルフォーマットで1つの秘密鍵。 - ".der"ファイル形式の証明書。 - ".der"ファイル形式のサーバーの1つのCA。 - ".der"ファイル形式の4096ビットのサーバーのCA。 – Henry198

+0

'X509IdentityToken'は、証明書のバイトを使って作成されます。私は、[OK]を –

0

彼のクラスX509IdentityProviderを使用してKevin Herronのヘルプで問題を解決しました。

PemFile.java

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStreamReader; 

import org.bouncycastle.util.io.pem.PemObject; 
import org.bouncycastle.util.io.pem.PemReader; 

public class PemFile { 

    private PemObject pemObject; 

    public PemFile(String filename) throws FileNotFoundException, IOException { 
     PemReader pemReader = new PemReader(new InputStreamReader(new FileInputStream(filename))); 
     try { 
      this.pemObject = pemReader.readPemObject(); 
     } finally { 
      pemReader.close(); 
     } 
    } 

    public PemObject getPemObject() { 
     return pemObject; 
    } 
} 

X509IdentityProvider.java

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStream; 
import java.nio.ByteBuffer; 
import java.security.GeneralSecurityException; 
import java.security.KeyFactory; 
import java.security.NoSuchAlgorithmException; 
import java.security.NoSuchProviderException; 
import java.security.PrivateKey; 
import java.security.Security; 
import java.security.cert.CertificateException; 
import java.security.cert.CertificateFactory; 
import java.security.cert.X509Certificate; 
import java.security.spec.InvalidKeySpecException; 
import java.security.spec.PKCS8EncodedKeySpec; 
import java.util.Arrays; 

import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import org.eclipse.milo.opcua.sdk.client.api.identity.IdentityProvider; 
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy; 
import org.eclipse.milo.opcua.stack.core.types.builtin.ByteString; 
import org.eclipse.milo.opcua.stack.core.types.enumerated.UserTokenType; 
import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription; 
import org.eclipse.milo.opcua.stack.core.types.structured.SignatureData; 
import org.eclipse.milo.opcua.stack.core.types.structured.UserIdentityToken; 
import org.eclipse.milo.opcua.stack.core.types.structured.UserTokenPolicy; 
import org.eclipse.milo.opcua.stack.core.types.structured.X509IdentityToken; 
import org.eclipse.milo.opcua.stack.core.util.SignatureUtil; 
import org.jooq.lambda.tuple.Tuple2; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class X509IdentityProvider implements IdentityProvider { 
    private final Logger logger = LoggerFactory.getLogger(getClass()); 
    private final X509Certificate certificate; 
    private final PrivateKey privateKey; 

    public X509Certificate getCertificate() { 
     return certificate; 
    } 

    public PrivateKey getPrivateKey() { 
     return privateKey; 
    } 

    public X509IdentityProvider(X509Certificate certificate, PrivateKey privateKey) { 
     this.certificate = certificate; 
     this.privateKey = privateKey; 
    } 

    public X509IdentityProvider(String certificate, String privateKey) { 
     this.certificate = loadCertificateFromDerFile(certificate); 

     Security.addProvider(new BouncyCastleProvider()); 
     KeyFactory kf; 
     PrivateKey privateKeyTmp = null; 
     try { 
      kf = KeyFactory.getInstance("RSA", "BC"); 
      privateKeyTmp = loadPrivateKeyFromPemFile(kf, privateKey); 
     } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeySpecException | IOException e) { 
      e.printStackTrace(); 
     } 
     this.privateKey = privateKeyTmp; 

    } 

    @Override 
    public Tuple2<UserIdentityToken, SignatureData> getIdentityToken(EndpointDescription endpoint, 
      ByteString serverNonce) throws Exception { 
     UserTokenPolicy tokenPolicy = Arrays.stream(endpoint.getUserIdentityTokens()) 
       .filter(t -> t.getTokenType() == UserTokenType.Certificate).findFirst() 
       .orElseThrow(() -> new Exception("no x509 certificate token policy found")); 
     String policyId = tokenPolicy.getPolicyId(); 
     SecurityPolicy securityPolicy = SecurityPolicy.Basic256; 
     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={}", securityPolicyUri); 
     } 
     X509IdentityToken token = new X509IdentityToken(policyId, ByteString.of(certificate.getEncoded())); 
     SignatureData signatureData; 
     ByteString serverCertificate = endpoint.getServerCertificate(); 
     byte[] serverCertificateBytes = serverCertificate.isNotNull() ? serverCertificate.bytes() : new byte[0]; 
     byte[] serverNonceBytes = serverNonce.isNotNull() ? serverNonce.bytes() : new byte[0]; 
     assert serverCertificateBytes != null; 
     assert serverNonceBytes != null; 
     byte[] signature = SignatureUtil.sign(securityPolicy.getAsymmetricSignatureAlgorithm(), privateKey, 
       ByteBuffer.wrap(serverCertificateBytes), ByteBuffer.wrap(serverNonceBytes)); 
     signatureData = new SignatureData(securityPolicy.getAsymmetricSignatureAlgorithm().getUri(), 
       ByteString.of(signature)); 
     return new Tuple2<>(token, signatureData); 
    } 


    private static X509Certificate loadCertificateFromDerFile(String filename) { 
     InputStream in; 
     X509Certificate cert = null; 
     try { 
      in = new FileInputStream(filename); 

      CertificateFactory factory = CertificateFactory.getInstance("X.509"); 
      cert = (X509Certificate) factory.generateCertificate(in); 
     } catch (FileNotFoundException | CertificateException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return cert; 
    } 

    private static PrivateKey loadPrivateKeyFromPemFile(KeyFactory factory, String filename) 
      throws InvalidKeySpecException, FileNotFoundException, IOException { 
     PemFile pemFile = new PemFile(filename); 
     byte[] content = pemFile.getPemObject().getContent(); 
     PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content); 
     return factory.generatePrivate(privKeySpec); 
    } 

} 
:ここ

は、溶液コードであります

ClientRunner.java

... 
... 

private OpcUaClient createClient() throws Exception { 
     SecurityPolicy securityPolicy = clientExample.getSecurityPolicy(); // For example : SecurityPolicy.Basic256 
     String securityMode = clientExample.getSecurityMode(); // For example : "SignAndEncrypt" 

     EndpointDescription[] endpoints = UaTcpStackClient.getEndpoints(endpointUrl).get(); 

     EndpointDescription endpoint = Arrays.stream(endpoints) 
       .filter(e -> e.getSecurityPolicyUri().equals(securityPolicy.getSecurityPolicyUri()))// 
       .filter(e -> e.getSecurityMode().toString().compareTo(securityMode) == 0)// 
       .findFirst()// 
       .orElseThrow(() -> new Exception("no desired endpoints returned")); 

     logger.info("Using endpoint: {} [{}]", endpoint.getEndpointUrl(), securityPolicy); 

     loader.load(); 

     // Mode : securityPolicy == SecurityPolicy.Basic256 && securityMode.compareTo("SignAndEncrypt") == 0) 
     X509IdentityProvider x509IdentityProvider = new X509IdentityProvider("/certificate.der", 
       "/privateKey.pem"); 
     X509Certificate cert = x509IdentityProvider.getCertificate(); 
     KeyPair keyPair = new KeyPair(cert.getPublicKey(), x509IdentityProvider.getPrivateKey()); 
     OpcUaClientConfig config = OpcUaClientConfig.builder().setApplicationName(LocalizedText.english("opc-ua client"))// 
       .setApplicationUri("urn:opcua client")// 
       .setCertificate(cert)// 
       .setKeyPair(keyPair)// 
       .setEndpoint(endpoint)// 
       .setIdentityProvider(x509IdentityProvider)// 
       .setIdentityProvider(clientExample.getIdentityProvider())// 
       .setRequestTimeout(uint(5000))// 
       .build(); 


     return new OpcUaClient(config); 
    } 
関連する問題