Sample Code
Java
Verify signing_cert_url, signature that obtained in HTTP or HTTPS Message Format, and message (contained in the message signature) to check the message validity, as shown in the following:
private static void isMessageValid(String signing_cert_url, String signature, Map<String, String> message) { InputStream in = null; try { URL url = new URL(signing_cert_url); in = url.openStream(); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(in); Signature sig = Signature.getInstance(cert.getSigAlgName()); sig.initVerify(cert.getPublicKey()); sig.update(buildSignMessage(message).getBytes("UTF-8")); byte[] sigByte = Base64.getDecoder().decode(signature); if (sig.verify(sigByte)) { System.out.println("Verify success"); } else { System.out.println("Verify failed"); } } catch (Exception e) { throw new SecurityException("Verify method failed.", e); } finally { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } }
If your Java version is earlier than 8, use the third-party package commons-codec.jar to perform Base64 decoding, and replace byte[] sigByte = Base64.getDecoder().decode(signature); with byte[] sigByte = Base64.decodeBase64(signature); in the preceding code.
The following is an example of the code to create the message verification signature:
private static String buildSignMessage(Map<String,String> msg) { String type = msg.get("type"); String message = null; if ("Notification".equals(type)){ message = buildNotificationMessage(msg); } else if ("SubscriptionConfirmation".equals(type) || "UnsubscribeConfirmation".equals(type)){ message = buildSubscriptionMessage(msg); } return message; } private static String buildSubscriptionMessage(Map<String, String> msg) { String stringMessage = "message\n"; stringMessage += msg.get("message") + "\n"; stringMessage += "message_id\n"; stringMessage += msg.get("message_id") + "\n"; stringMessage += "subscribe_url\n"; stringMessage += msg.get("subscribe_url") + "\n"; stringMessage += "timestamp\n"; stringMessage += msg.get("timestamp") + "\n"; stringMessage += "topic_urn\n"; stringMessage += msg.get("topic_urn") + "\n"; stringMessage += "type\n"; stringMessage += msg.get("type") + "\n"; return stringMessage; } private static String buildNotificationMessage(Map<String, String> msg) { String stringMessage = "message\n"; stringMessage += msg.get("message").toString() + "\n"; stringMessage += "message_id\n"; stringMessage += msg.get("message_id").toString() + "\n"; if (msg.get("subject") != null){ stringMessage += "subject\n"; stringMessage += msg.get("subject").toString() + "\n"; } stringMessage += "timestamp\n"; stringMessage += msg.get("timestamp").toString() + "\n"; stringMessage += "topic_urn\n"; stringMessage += msg.get("topic_urn").toString() + "\n"; stringMessage += "type\n"; stringMessage += msg.get("type").toString() + "\n"; return stringMessage; }
Node.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
const fs = require('fs'); const crypto = require('crypto'); const jsrsag = require('jsrsasign'); /** * Message signature verification * @param pemFile: path for storing the signature file (path for storing the certificate downloaded to your local computer) * @param signature: signature to be verified * @param message: content of the message to be verified * @returns {boolean} true: The signature passes the verification. false: The signature fails the verification. */ function verifyMessage(pemFile, signature, message) { const pubPem = fs.readFileSync(pemFile); const verify = crypto.createVerify(signatureAlgorithm(pubPem)); verify.update(buildSignMessage(message)); const verifyResult = verify.verify(pubPem, signature, 'base64'); if (verifyResult) { console.log("verify success"); return true; } else { console.log('verify failed, result: ' + verifyResult); return false; } } /** * Obtain the signature algorithm from the certificate. */ function signatureAlgorithm(pubPem) { const certObject = new jsrsag.X509(); certObject.readCertPEM(pubPem.toString()); let algorithm = certObject.getSignatureAlgorithmField(); if (algorithm.split('with').length > 1) { algorithm = algorithm.split('with')[1] + '-' + algorithm.split('with')[0]; } return algorithm; } function buildSignMessage(msg) { const type = msg.type; let message = ''; if (type === 'Notification') { message = buildNotificationMessage(msg); } else if (type === 'SubscriptionConfirmation') { message = buildSubscriptionMessage(msg); } return message; } function buildNotificationMessage(msg) { let signMessage = 'message\n' + msg.message + '\n'; signMessage += 'message_id\n' + msg.message_id + '\n'; if (msg.subject) { signMessage += 'subject\n' + msg.subject + '\n'; } signMessage += 'timestamp\n' + msg.timestamp + '\n'; signMessage += 'topic_urn\n' + msg.topic_urn + '\n'; signMessage += 'type\n' + msg.type + '\n'; return signMessage; } function buildSubscriptionMessage(msg) { let signMessage = 'message\n' + msg.message + '\n'; signMessage += 'message_id\n' + msg.message_id + '\n'; signMessage += 'subscribe_url\n' + msg.subscribe_url + '\n'; signMessage += 'timestamp\n' + msg.timestamp + '\n'; signMessage += 'topic_urn\n' + msg.topic_urn + '\n'; signMessage += 'type\n' + msg.type + '\n'; return signMessage; } |
The sample code has passed the test on Nodejs v14.17.5.
Go
package demo import ( "bytes" "crypto" "crypto/rsa" "crypto/x509" "encoding/base64" "encoding/json" "encoding/pem" "fmt" "io/ioutil" ) type Message struct { Signature string `json:"signature"` Subject *string `json:"subject"` TopicUrn string `json:"topic_urn"` MessageId string `json:"message_id"` SignatureVersion string `json:"signature_version"` Type string `json:"type"` Message string `json:"message"` SubscribeUrl string `json:"subscribe_url"` UnsubscribeUrl string `json:"unsubscribe_url"` SigningCertUrl string `json:"signing_cert_url"` Timestamp string `json:"timestamp"` } func VerifyMessage(pemFile string, message string) bool { msg := Message{} err := json.Unmarshal([]byte(message), &msg) if err != nil { fmt.Println("Convert json to struct failed") return false } pemContent, err := ioutil.ReadFile(pemFile) if err != nil { fmt.Println("Read pem file failed") return false } certDerblock, _ := pem.Decode(pemContent) if certDerblock == nil { fmt.Println("Decode pem file failed") return false } cert, err := x509.ParseCertificate(certDerblock.Bytes) if err != nil { fmt.Println("Parse cert failed") return false } msgString := buildMessage(&msg) msgHash := crypto.SHA256.New() msgHash.Write([]byte(msgString)) msgHashSum := msgHash.Sum(nil) decodeSign, _ := base64.StdEncoding.DecodeString(msg.Signature) publicKey := cert.PublicKey.(*rsa.PublicKey) err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, msgHashSum, decodeSign) if err != nil { fmt.Println("Verify failed") return false } else { fmt.Println("Verify success") return true } } func buildMessage(msg *Message) string { if msg.Type == "Notification" { return buildNotificationMessage(msg) } else if msg.Type == "SubscriptionConfirmation" || msg.Type == "UnsubscribeConfirmation" { return buildSubscriptionMessage(msg) } return "" } func buildNotificationMessage(msg *Message) string { buf := bytes.Buffer{} buf.WriteString("message\n" + msg.Message + "\n") buf.WriteString("message_id\n" + msg.MessageId + "\n") //The Subject field does not exist in msg, and this issue needs to be addressed. if msg.Subject != nil { buf.WriteString("subject\n" + *msg.Subject + "\n") } buf.WriteString("timestamp\n" + msg.Timestamp + "\n") buf.WriteString("topic_urn\n" + msg.TopicUrn + "\n") buf.WriteString("type\n" + msg.Type + "\n") return buf.String() } func buildSubscriptionMessage(msg *Message) string { buf := bytes.Buffer{} buf.WriteString("message\n" + msg.Message + "\n") buf.WriteString("message_id\n" + msg.MessageId + "\n") buf.WriteString("subscribe_url\n" + msg.SubscribeUrl + "\n") buf.WriteString("timestamp\n" + msg.Timestamp + "\n") buf.WriteString("topic_urn\n" + msg.TopicUrn + "\n") buf.WriteString("type\n" + msg.Type + "\n") return buf.String() }
The sample code has passed the test on Go 11.5
Feedback
Was this page helpful?
Provide feedbackThank you very much for your feedback. We will continue working to improve the documentation.