7
votes

Java SSL Code jetant nosuchalgorithexception

Je travaille sur un projet que je souhaite ajouter SSL à, j'ai donc créé une implémentation de test client / serveur simple pour voir si elle fonctionnait et que je reçois une noschalgorithmexception. Ce qui suit est mon code de serveur qui jette l'exception: xxx

La stacktrace i get est: xxx

J'ai essayé de remplacer "TLS" avec "SSL" et j'ai toujours eu la même exception. Cela n'avait pas de sens pour moi. Comment TLS et SSL peuvent-ils ne pas être pris en charge? C'est mon premier temps d'essayer de mettre en œuvre SSL et il semble difficile de trouver de bonnes ressources à ce sujet avec des exemples de code bien expliqués. Quelqu'un peut-il me dire pourquoi je reçois cette exception ou soulignez quelque chose de mal avec mon code?


0 commentaires

3 Réponses :


16
votes

Il y a un certain nombre de problèmes:

  • Ça s'appelle TLS (Sécurité de la couche de transport), pas TSL (pour le SSLContext ).
  • Je suggère d'utiliser la valeur par défaut ici: TrustManagerFactory TMF = TrustManagerFactory.getinstance (FredManagerFactory.getDefaultalgorithm ()) (La valeur par défaut sera PKIX SUR LE Oracle JRE` )
  • ( EDIT: ) La valeur par défaut KeyManagerFactory est sunx509 ( tls n'existe pas ici). Encore une fois, utilisez getDefaultalgorithm () .
  • Vous devez fermer votre FileInputStream une fois que vous les avez lu.
  • Ce n'est pas clair pourquoi vous avez à la fois un client et un magasin de clés de serveur au même endroit. Ceux-ci devraient être deux programmes: un pour le client et le serveur (et SetNeedClientauthuth (true) est uniquement utile sur le côté serveur). Il serait plus clair de l'appeler autre chose que "client client" si c'est effectivement votre clé de clés. (En outre, puisque vous semblez apprendre à faire ce travail, je suggérerais d'essayer d'abord d'essayer sans authentification de certificat client, auquel cas, le serveur n'aura pas besoin d'une dépôt de fiducies: Utilisez null En tant que deuxième paramètre de sslContext.init (...) pour utiliser la valeur par défaut.)
  • Ne donnez pas de clé de clés de serveur au client. Seuls l'exportation de son certificat en un nouveau keyStore que vous utiliserez comme magasin de fiducie. Chaque entité (client et serveur) devrait conserver ses propres clés privées privées.
  • Ce n'est pas tant la clé publique (seulement) de la partie distante que vous souhaitez dans votre magasin Trust-Store: ça va être son certificat . Assurez-vous de ne pas importer que sa clé publique, mais tout le certificat.
  • Pour clarifier, conservez les extensions appropriées dans vos fichiers: Utilisez .jks pour votre jks KeyStore, cela vous permettra de sauvegarder des maux de tête plus tard.
  • Vous pouvez utiliser null pour le SE SIERURANDOM dans SSLContext.init (...) : Cela utilisera la valeur par défaut en fonction de la valeur Fournisseur de sécurité.

    Quelque chose comme ça devrait mieux fonctionner: xxx


9 commentaires

K j'ai édité mon message pour ajouter ce changement. J'ai toujours la même exception même lorsque j'utilise "TLS"


Si vous êtes vraiment inquiet pour les mots de passe, vous devez utiliser un char [] directement ou comme rappel du mot de passe, et ne jamais coder votre mot de passe de toute façon dans une application réelle (voir Stackoverflow.com/a/8889285/372643 ).


Comme une note latérale, en attente de readline pour retourner null n'est pas un bon moyen de savoir quand arrêter de lire (de n'importe quelle sorte de prise), voir la discussion ici: Stackoverflow.com/a/6425509/372643


J'ai changé mon code pour utiliser TrustManagerFactory.getDefaultalgorithM () et KeyManagerFactory.getDefaultalgorithm () et qui a eu le travail. La raison pour laquelle j'ai les deux keystores ici est que le serveur a: serveur.private et client.Public, tandis que le client aura client.private et Server.Public. BTW, j'ai utilisé ce site comme référence pour mon code, je ne sais pas à quel point il est fiable, mais c'est le meilleur que je pouvais trouver: www.ibm.com/developerworks/java/Tutorials/j-jsse/index.html


Il a dit sunx509 pour le KMF, pas tls . Il utilise également une version assez ancienne de Java, la nouvelle valeur par défaut du TMF est pKix . (Je ne suis toujours pas convaincu de la convention de dénomination du fichier KeyStore dans cet article.)


Au lieu d'utiliser .private et .Public devrais-je simplement les faire .JKS? En outre, en référence à l'article sur la fermeture SSLSocket correctement, comment détecterai-je le close_notify sur le serveur lorsque le client appelle socket.close () ?


À propos des fichiers, vous pourriez également simplement ajouter .jks , oui. À propos de la fermeture des sockets, c'est un problème de réseautage plus général: vous ne pouvez généralement pas distinguer les prises silencieuses et anormalement fermées. C'est pourquoi les protocoles utilisent un indicateur pour indiquer la quantité de données qu'ils vont envoyer (et vous devez généralement définir une valeur du délai d'expiration): Par exemple, http a longueur de contenu et codage de transfert de contenu dire au destinataire lorsque le message attendu est terminé. D'autres protocoles ont d'autres délimiteurs.


C'est le problème avec mon programme. Plusieurs clients se connecteront au serveur, ils enverront de nombreux messages jusqu'à ce que le client se déconnecte. Je suppose que vous pouvez penser à cela un peu comme une salle de discussion multi-utilisateurs. Donc, depuis que je ne sais pas avant de la main combien de données ou combien de messages seront envoyés, je viens de vérifier la fin de la bufferedreader. Utiliser cette méthode toujours considérée comme une mauvaise pratique ou est-ce acceptable?


Ne vérifiez pas la fin du lecteur. Cela pourrait fonctionner la plupart du temps afin de ne pas voir le problème, mais étudiez d'autres protocoles. HTTP, POP, IMAP, SMTP ont tous une forme de délimiteurs à indiquer à la partie distante lorsqu'elles sont terminées (et en attente d'un autre message). Chaque fois que vous envoyez un nouveau message dans votre chat (qui peut être représenté ou non par un "message" au niveau de votre protocole d'application), utilisez un indicateur pour dire quand il va se terminer.



1
votes

Le nom de SSLContext correct est "TLS". Une liste des noms d'algorithme standard peut être trouvé ici.


2 commentaires

C'était un mathype et a été corrigé. Je reçois toujours l'exception avec "TLS"


Voir Modification de Bruno à sa réponse concernant la clé KeyManagerFactory, ce serait votre autre problème.



3
votes

Voir http: // docs .Oracle.com / Javase / 6 / Documents / Technotes / Guides / Security / JSSE / JSSEFGUIDE.HTML # SupportClasses Pour des exemples et pour les noms de l'algorithme pris en charge. Il semble que "Sunx509" et "Newsunx509" sont les algorithmes soutenus par KeyManagerFactory. Et le protocole est nommé TLS, pas TSL.


3 commentaires

Encore une fois, c'était un mistpe et a été corrigé. Je reçois toujours l'exception avec "TLS"


Avez-vous lu ma réponse? Il semble que "Sunx509" et "Newsunx509" sont les algorithmes supportés par KeyManagerFactory .


+ 1'ed (comme j'avais fait une faute de frappe dans ma réponse initiale x509 -> sunx509 ). @ Mattl922: getDefaultalgorithm () est souvent le pari le plus sûr.