دسترسی آنلاین تقریباً به هر چیزی و تعامل با یکدیگر بخشی از روال روزانه ماست. اما زندگی در دنیای آنلاین به این معنی است که باید مشروعیت دادهها را زیر سؤال ببرید: آیا هر ایمیلی قابل اعتماد است؟ وقتی به وبسایت مورد علاقه خود وارد میشوید، چگونه میدانید قابل اعتماد است؟ آیا بهروزرسانی نرمافزاری که میخواهید نصب کنید واقعی است، یا یک ویروس مخفی است که منتظر آلوده کردن دستگاه شماست؟
در این مقاله نگاهی دقیقتر به نحوه تأیید امضاها و بازرسی گواهینامهها در کد جاوا خواهیم داشت.
اگر به مکانیزمی برای تأیید نیاز دارید، باید از امضاهای دیجیتال استفاده کنید:
برای ارسال پیام با امضای دیجیتال ابتدا باید یک جفت کلید نامتقارن با الگوریتمی مانند Ed25519 تولید کنید:
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(Ed25519);
KeyPair keypair = keyPairGenerator.generateKeyPair();
سپس پیام را به شیء Signature خورانده و متود sign را فراخوانی کنید:
public static byte[] generateDigitalSignature(byte[] plainText, PrivateKey privateKey) throws Exception {
Signature signature = Signature.getInstance("Ed25519");
signature.initSign(privateKey);
signature.update(plainText);
return signature.sign();
}
در متود generateDigitalSignature، نمونهای از شیء Signature با الگوریتم امضا Ed25519 دریافت میکنید. این یک الگوریتم امضای منحنی بیضوی است که از EdDSA و Curve25519 استفاده میکند. سپس Signature را با کلید خصوصی مقداردهی اولیه کرده، پیام را پاس داده و عملیات امضا را بهصورت آرایهای از بایتها ذخیره میکنید.
برای تأیید یک امضا، دوباره یک نمونه Signature ایجاد کنید و این بار متن پیام و کلید عمومی را پاس دهید:
public static boolean verifyDigitalSignature(byte[] plainText, byte[] digitalSignature, PublicKey publicKey)
throws Exception {
Signature signature = Signature.getInstance("Ed25519");
signature.initVerify(publicKey);
signature.update(plainText);
return signature.verify(digitalSignature);
}
در نهایت میتوانید امضا را با فراخوانی متود verify بررسی کنید.
برای امتحان متدهای بالا، کد زیر را در jshell اجرا کنید:
import java.security.*;
import java.util.HexFormat;
import java.util.Scanner;
public class DigitalSignatureExample {
public static final String Ed25519 = "Ed25519";
public static byte[] generateDigitalSignature(byte[] plainText, PrivateKey privateKey) throws Exception {
Signature signature = Signature.getInstance(Ed25519);
signature.initSign(privateKey);
signature.update(plainText);
return signature.sign();
}
public static boolean verifyDigitalSignature(byte[] plainText, byte[] digitalSignature, PublicKey publicKey)
throws Exception {
Signature signature = Signature.getInstance(Ed25519);
signature.initVerify(publicKey);
signature.update(plainText);
return signature.verify(digitalSignature);
}
public static void main(String[] args) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("Ed25519");
KeyPair keypair = keyPairGenerator.generateKeyPair();
Scanner message = new Scanner(System.in);
IO.print("Enter the message you want to encrypt using Ed25519: ");
String plainText = message.nextLine();
byte[] bytes = plainText.getBytes();
message.close();
byte[] digitalSignature = generateDigitalSignature(bytes, keypair.getPrivate());
IO.println("Signature Value:\n " + HexFormat.of().formatHex(digitalSignature));
IO.println("Verification: " + verifyDigitalSignature(bytes, digitalSignature, keypair.getPublic()));
}
}
در رمزنگاری، گواهینامهها اسناد الکترونیکی هستند که اطلاعاتی مانند هویت کاربر و کلید عمومی را به هم پیوند میدهند. یک طرف سوم مورد اعتماد — مرجع صدور گواهی (Certificate Authority - CA) — گواهینامههای دیجیتال را برای تأیید هویت دارنده گواهینامه صادر میکند.
شکل ۱: بخشی از گواهینامه از خروجی keytool -printcert -sslserver oracle.com/java
یک گواهینامه دیجیتال شامل موارد زیر است:
برای درک بهتر تفاوت بین امضا و گواهینامه، جدول زیر را ببینید:
| ویژگی | امضای دیجیتال | گواهینامه دیجیتال |
|---|---|---|
| هدف | تأیید اصالت، یکپارچگی، عدم انکار | تأیید هویت فرستنده و دریافتکننده |
| فرآیند | الگوریتم رمزنگاری با کلید خصوصی روی پیام اعمال میشود تا امضای دیجیتال یکتا تولید شود | توسط مرجع صدور گواهی (CA) تولید میشود: تولید کلید، ثبتنام، تأیید، ایجاد |
| استاندارد | استاندارد امضای دیجیتال (DSS) | فرمت استاندارد X.509 |
گواهینامههایی که توسط یک مرجع صدور گواهی شناختهشده صادر نشدهاند بلکه توسط سرور میزبان صادر شدهاند، خودامضا (Self-Signed) نامیده میشوند.
میتوانید یک گواهینامه خودامضا با اعتبار ۳۶۵ روز با keytool ایجاد کنید:
$ keytool -genkeypair -keyalg ed25519 -alias mykey -keystore mykeystore.jks -storepass jkspass \
-dname "CN=server.mycompany.com,OU=My Company Dev Team,O=My Company,c=NL" -validity 365
> Generating 255 bit Ed25519 key pair and self-signed certificate (Ed25519)
> with a validity of 365 days for: CN=server.mycompany.com, OU=My Company Dev Team, O=My Company, C=NL
دستور بالا چندین عملیات انجام میدهد:
mykeystore ایجاد کرده و رمز عبور jkspass را به آن اختصاص میدهد.Ed25519 استفاده میکند.میتوانید گواهینامه مرتبط با یک نام مستعار (Alias) را از KeyStore بخوانید و آن را در فایلی ذخیره کنید:
$ keytool -exportcert -alias mykey \
-keystore mykeystore.jks -storepass jkspass -rfc -file mycert.pem
> Certificate stored in file <mycert.pem>
برای تجزیه و مدیریت این گواهینامه میتوانید از keytool یا کلاسهای پکیج java.security.cert استفاده کنید. بهعنوان مثال، میتوانید یک java.security.cert.Certificate تولید کرده و آن را به java.security.cert.X509Certificate Cast کنید:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
public class CertificateManagementExample {
public static void main(String[] args) throws Exception {
//generate a certificate object
X509Certificate cert = extractCertificate("mycert.pem");
}
private static X509Certificate extractCertificate(String filePath) throws IOException, CertificateException {
try (InputStream is = new FileInputStream(filePath)) {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
return (X509Certificate) certificateFactory.generateCertificate(is);
}
}
}
کلاس java.security.cert.Certificate یک انتزاع برای گواهینامهها با فرمتهای مختلف است و java.security.cert.X509Certificate روش استانداردی برای دسترسی به تمام Attribute های یک گواهینامه X.509 ارائه میدهد.
هنگام کار با گواهینامههای دیجیتال، میتوانید با استفاده از Thumbprint گواهینامه بهسرعت یک گواهینامه خاص را در Credential Store سیستم خود پیدا کنید. Fingerprint گواهینامه شناسه یکتای آن است و میتواند برای مقایسه گواهینامهها کمک کند. میتوانید Thumbprint را با java.security.MessageDigest محاسبه کنید:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HexFormat;
public class CertificateManagementExample {
public static void main(String[] args) throws Exception {
//generate a certificate object
X509Certificate cert = extractCertificate("mycert.pem");
//compute thumbprint
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(cert.getEncoded());
IO.println(HexFormat.ofDelimiter(":").formatHex(md.digest()));
}
private static X509Certificate extractCertificate(String filePath) throws IOException, CertificateException {
try (InputStream is = new FileInputStream(filePath)) {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
return (X509Certificate) certificateFactory.generateCertificate(is);
}
}
}
تبریک! تفاوت بین امضاهای دیجیتال و گواهینامههای دیجیتال و نحوه تعامل با آنها در جاوا با استفاده از Java Security API را آموختید.
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://dev.java/learn/