Java >> Java Tutorial >  >> Java

NoSuchAlgorithmException:Algorithmus HmacSHA1 nicht verfügbar

Sehen Sie sich die folgende Java-Zeile an:

Mac.getInstance("HmacSHA1");

Wenn ich das in ein einfaches Testprogramm stecke, läuft es ohne Probleme auf meinem Server. Wenn ich diese Zeile jedoch in einem Container verwende, bekomme ich

java.security.NoSuchAlgorithmException: Algorithm HmacSHA1 not available
  at javax.crypto.Mac.getInstance(DashoA13*..)

In beiden Fällen wird dieselbe JDK-Installation verwendet.

Nachdem ich ein bisschen herumgegoogelt hatte, gelang es mir, es zum Laufen zu bringen, indem ich zwei Dinge tat:

  1. Kopieren von sunjce_provider.jar ab $JAVA_HOME/jre/lib/ext in das lib-Verzeichnis des Containers.
  2. Hinzufügen der folgenden Zeile zu meinem Code:

    java.security.Security.addProvider(new com.sun.crypto.provider.SunJCE());

Insbesondere passiert mir das in einem Mailet von Apache James, aber ich bin mir ziemlich sicher, dass dies mit JVM-Optionen zu tun hat. Hier ist das verwendete Startskript.

Obwohl ich es am Ende zum Laufen gebracht habe, fühlt sich die Lösung zu gehackt an, um die richtige zu sein. Ich würde mich über eine Erklärung dessen, was vor sich geht, sowie über eine „richtigere“ Lösung freuen.

Verwandte Frage :Die Verwendung von Java-Krypto führt zu NoSuchAlgorithmException. In diesem Fall bin ich mir jedoch ziemlich sicher, dass der HmacSHA1-Algorithmus standardmäßig unterstützt werden sollte. Zum Beweis funktioniert das in einem Testprogramm problemlos.

Antwort

Das Startskript setzt den java.ext.dirs in einen eigenen Satz von Verzeichnissen (spezifisch für die Anwendung), aber unter Weglassung des „normalen“ Erweiterungsverzeichnisses ($JAVA_HOME/jre/lib/ext/ ), wo sunjce_provider.jar steht wohnt. Dies erklärt Ihren ersten Punkt (das Kopieren der Jar-Datei in das lib-Verzeichnis macht sie wieder sichtbar). Dies lässt sich leicht reproduzieren.

Was den zweiten Punkt betrifft, denke ich, dass dies an der Richtliniendatei liegt, die das Startskript mit dem -Djava.security.policy festlegt Möglichkeit. Ob einige Anbieter verfügbar sind oder nicht, hängt von Richtliniendateien ab. Die Standardrichtliniendatei stellt den SunJCE-Anbieter zur Verfügung, aber da die Startskripts eine nicht standardmäßige, benutzerdefinierte Richtliniendatei vorschreiben, ist alles möglich. Ich schlage vor, Sie werfen einen Blick auf diese Richtliniendatei.

Auf meinem System (Ubuntu Linux, mit Sun JVM 1.6.0_20, wie von Ubuntu gepackt) befindet sich die Standardrichtliniendatei beispielsweise in /etc/java-6-sun/security/java.security und enthält (unter anderem) die folgenden Zeilen:

security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=com.sun.net.ssl.internal.ssl.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider
security.provider.6=com.sun.security.sasl.Provider
security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.8=sun.security.smartcardio.SunPCSC

die definieren, welche Anbieter standardmäßig verfügbar sein sollen. Aufgrund Ihrer Symptome denke ich, dass die benutzerdefinierte Richtliniendatei SunJCE nicht verfügbar gemacht hat, es sei denn, es wurde explizit registriert (was verständlich ist, da das Startskript auch den Zugriff auf die Jar-Datei mit SunJCE entfernt hat …).


Java-Tag