Commit 60ba64b2 authored by Lukas Matt's avatar Lukas Matt Committed by GitHub

Merge pull request #8 from ganggo/add_signature_verification

Fix signature verification by using xml order
parents da96e258 3b113da5
......@@ -50,11 +50,13 @@ type Entity struct {
Data interface{} `xml:"-"`
}
type Time struct {
time.Time
type Time string
func (m Message) Signature() string {
return m.Sig.Sig
}
func (m Message) SignatureText() []string {
func (m Message) SignatureText(order string) []string {
return []string{
m.Data.Data,
base64.StdEncoding.EncodeToString([]byte(m.Data.Type)),
......@@ -63,20 +65,17 @@ func (m Message) SignatureText() []string {
}
}
func (t *Time) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
e.EncodeElement(t.Format(TIME_FORMAT), start)
return nil
func (t *Time) New(newTime time.Time) *Time {
*t = Time(newTime.UTC().Format(TIME_FORMAT))
return t
}
func (t *Time) UnmarshalXML(decoder *xml.Decoder, start xml.StartElement) error {
var value string
decoder.DecodeElement(&value, &start)
parse, err := time.Parse(TIME_FORMAT, value)
if err != nil {
return err
}
*t = Time{parse}
return nil
func (t Time) Time() (time.Time, error) {
return time.Parse(TIME_FORMAT, string(t))
}
func (t Time) String() string {
return string(t)
}
func (e *Entity) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
......
......@@ -19,106 +19,41 @@ package federation
import (
"testing"
"reflect"
"github.com/Zauberstuhl/go-xml"
)
func TestEntitiesUnmarshalXML(t *testing.T) {
var entity Entity
var retractionRaw = []byte(`<retraction></retraction>`)
var profileRaw = []byte(`<profile></profile>`)
var statusMessageRaw = []byte(`<status_message></status_message>`)
var reshareRaw = []byte(`<reshare></reshare>`)
var commentRaw = []byte(`<comment></comment>`)
var likeRaw = []byte(`<like></like>`)
var contactRaw = []byte(`<contact></contact>`)
var notSupportedRaw = []byte(`<notsupported></notsupported>`)
err := xml.Unmarshal(retractionRaw, &entity)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
if data, ok := entity.Data.(EntityRetraction); !ok {
t.Errorf("Expected to be 'like', got %v", data)
}
err = xml.Unmarshal(retractionRaw[:len(retractionRaw)-1], &entity)
if err == nil {
t.Errorf("Expected an error, got nil")
}
err = xml.Unmarshal(profileRaw, &entity)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
if data, ok := entity.Data.(EntityProfile); !ok {
t.Errorf("Expected to be 'profile', got %v", data)
}
err = xml.Unmarshal(profileRaw[:len(profileRaw)-1], &entity)
if err == nil {
t.Errorf("Expected an error, got nil")
}
err = xml.Unmarshal(statusMessageRaw, &entity)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
if data, ok := entity.Data.(EntityStatusMessage); !ok {
t.Errorf("Expected to be 'status_message', got %v", data)
}
err = xml.Unmarshal(statusMessageRaw[:len(statusMessageRaw)-1], &entity)
if err == nil {
t.Errorf("Expected an error, got nil")
}
err = xml.Unmarshal(reshareRaw, &entity)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
if data, ok := entity.Data.(EntityReshare); !ok {
t.Errorf("Expected to be 'reshare', got %v", data)
}
err = xml.Unmarshal(reshareRaw[:len(reshareRaw)-1], &entity)
if err == nil {
t.Errorf("Expected an error, got nil")
var tests = []struct{
Type string
Raw []byte
}{
{Type: "EntityRetraction", Raw: []byte(`<retraction></retraction>`)},
{Type: "EntityProfile", Raw: []byte(`<profile></profile>`)},
{Type: "EntityStatusMessage", Raw: []byte(`<status_message></status_message>`)},
{Type: "EntityReshare", Raw: []byte(`<reshare></reshare>`)},
{Type: "EntityComment", Raw: []byte(`<comment></comment>`)},
{Type: "EntityLike", Raw: []byte(`<like></like>`)},
{Type: "EntityContact", Raw: []byte(`<contact></contact>`)},
}
err = xml.Unmarshal(commentRaw, &entity)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
if data, ok := entity.Data.(EntityComment); !ok {
t.Errorf("Expected to be 'comment', got %v", data)
}
err = xml.Unmarshal(commentRaw[:len(commentRaw)-1], &entity)
if err == nil {
t.Errorf("Expected an error, got nil")
for i, test := range tests {
err := xml.Unmarshal(test.Raw, &entity)
if err != nil {
t.Errorf("#%d: Some error occured while parsing: %v", i, err)
}
name := reflect.TypeOf(entity.Data).Name()
if test.Type != name {
t.Errorf("#%d: Expected to be '%s', got '%s'", i, test.Type, name)
}
err = xml.Unmarshal(test.Raw[:len(test.Raw)-1], &entity)
if err == nil {
t.Errorf("#%d: Expected an error, got nil", i)
}
}
err = xml.Unmarshal(likeRaw, &entity)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
if data, ok := entity.Data.(EntityLike); !ok {
t.Errorf("Expected to be 'like', got %v", data)
}
err = xml.Unmarshal(likeRaw[:len(likeRaw)-1], &entity)
if err == nil {
t.Errorf("Expected an error, got nil")
}
err = xml.Unmarshal(contactRaw, &entity)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
if data, ok := entity.Data.(EntityContact); !ok {
t.Errorf("Expected to be 'contact', got %v", data)
}
err = xml.Unmarshal(contactRaw[:len(contactRaw)-1], &entity)
if err == nil {
t.Errorf("Expected an error, got nil")
}
err = xml.Unmarshal(notSupportedRaw, &entity)
err := xml.Unmarshal([]byte(`<not-supported></not-supported>`), &entity)
if err == nil {
t.Errorf("Expected an error, got nil")
}
......@@ -138,9 +73,8 @@ func TestEntitiesTimeMarshalAndUnmarshal(t *testing.T) {
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
if origTime.CreatedAt.Time.Format(TIME_FORMAT) != time {
t.Errorf("Expected to be '%s', got '%s'",
origTime.CreatedAt.Time.Format(TIME_FORMAT))
if origTime.CreatedAt.String() != time {
t.Errorf("Expected to be '%s', got '%s'", origTime.CreatedAt.String())
}
result, err := xml.Marshal(origTime)
......@@ -151,8 +85,19 @@ func TestEntitiesTimeMarshalAndUnmarshal(t *testing.T) {
t.Errorf("Expected to be '%s', got '%s'", result, rawXml)
}
err = xml.Unmarshal([]byte("<time><CreatedAt></CreatedAt></time>"), &origTime)
if err == nil {
t.Errorf("Expected an error, got nil")
timeTime, err := origTime.CreatedAt.Time()
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
if timeTime.Format(TIME_FORMAT) != time {
t.Errorf("Expected to be '%s', got '%s'",
time, timeTime.Format(TIME_FORMAT))
}
// XXX the application server uses time.Now if this happens
// we should change that and let the library decide what is best
//err = xml.Unmarshal([]byte("<time><CreatedAt></CreatedAt></time>"), &origTime)
//if err == nil {
// t.Errorf("Expected an error, got nil")
//}
}
......@@ -29,10 +29,17 @@ type EntityComment struct {
AuthorSignature string `xml:"author_signature"`
}
func (e EntityComment) SignatureText() []string {
func (e EntityComment) Signature() string {
return e.AuthorSignature
}
func (e EntityComment) SignatureText(order string) (signatureOrder []string) {
if order != "" {
return ExractSignatureText(order, e)
}
return []string{
e.Author,
e.CreatedAt.Format(TIME_FORMAT),
e.CreatedAt.String(),
e.Guid,
e.ParentGuid,
e.Text,
......
......@@ -22,16 +22,25 @@ import (
"time"
)
func TestCommentAppendSignature(t *testing.T) {
comment := EntityComment{
Author: "author@localhost",
Guid: "1234",
CreatedAt: Time{time.Now()},
ParentGuid: "4321",
Text: "hello world",
var comment = EntityComment{
Author: "author@localhost",
Guid: "1234",
ParentGuid: "4321",
AuthorSignature: "1234",
Text: "hello world",
}
func TestCommentSignature(t *testing.T) {
if comment.Signature() != comment.AuthorSignature {
t.Errorf("Expected to be '%s', got '%s'",
comment.AuthorSignature, comment.Signature())
}
}
func TestCommentAppendSignature(t *testing.T) {
comment.CreatedAt.New(time.Now())
if comment.AuthorSignature != "" {
if comment.AuthorSignature != "1234" {
t.Errorf("Expected to be empty, got %s", comment.AuthorSignature)
}
......
......@@ -32,7 +32,15 @@ type EntityLike struct {
SignatureOrder string `xml:"-"`
}
func (e EntityLike) SignatureText() []string {
func (e EntityLike) Signature() string {
return e.AuthorSignature
}
func (e EntityLike) SignatureText(order string) []string {
if order != "" {
return ExractSignatureText(order, e)
}
positive := "false"
if e.Positive {
positive = "true"
......
......@@ -19,15 +19,23 @@ package federation
import "testing"
func TestLikeAppendSignature(t *testing.T) {
like := EntityLike{
Positive: true,
Guid: "1234",
ParentGuid: "4321",
ParentType: "Post",
Author: "author@localhost",
var like = EntityLike{
Positive: true,
Guid: "1234",
ParentGuid: "4321",
ParentType: "Post",
Author: "author@localhost",
}
func TestLikeSignature(t *testing.T) {
like.AuthorSignature = "1234"
if like.Signature() != like.AuthorSignature {
t.Errorf("Expected to be '%s', got '%s'",
like.AuthorSignature, like.Signature())
}
}
func TestLikeAppendSignature(t *testing.T) {
privKey, err := ParseRSAPrivateKey(TEST_PRIV_KEY)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
......
......@@ -23,8 +23,47 @@ import (
"crypto/x509"
"encoding/pem"
"errors"
"reflect"
"strings"
)
func ExractSignatureText(order string, entity interface{}) (signatureOrder []string) {
orderArr := strings.Split(order, " ")
typeOf := reflect.TypeOf(entity)
var mappingFields = map[string]int{}
for i := 0; i < typeOf.NumField(); i++ {
field := typeOf.Field(i)
xmlTag := field.Tag.Get("xml")
if xmlTag != "" {
xmlOpts := strings.Split(xmlTag, ",")
if len(xmlOpts) > 0 && strings.Contains(order, xmlOpts[0]) {
mappingFields[xmlOpts[0]] = i
}
}
}
valueOf := reflect.ValueOf(entity)
for _, orderElem := range orderArr {
if i, ok := mappingFields[orderElem]; ok {
if value, ok := valueOf.Field(i).Interface().(Time); ok {
signatureOrder = append(signatureOrder, string(value))
}
if value, ok := valueOf.Field(i).Interface().(string); ok {
signatureOrder = append(signatureOrder, value)
}
if value, ok := valueOf.Field(i).Interface().(bool); ok {
valueBool := "false"
if value {
valueBool = "true"
}
signatureOrder = append(signatureOrder, valueBool)
}
}
}
return
}
func ParseRSAPublicKey(decodedKey []byte) (*rsa.PublicKey, error) {
block, _ := pem.Decode(decodedKey)
if block == nil {
......
......@@ -20,6 +20,7 @@ package federation
import (
"crypto/rsa"
"testing"
"strings"
)
var TEST_AUTHOR = `diaspora_2nd@localhost:3001`
......@@ -149,3 +150,39 @@ func TestParseStringHelper(t *testing.T) {
t.Errorf("Expected an error, got nil")
}
}
func TestExractSignatureText(t *testing.T) {
var entity = EntityComment {
Author: "1",
CreatedAt: "2",
Guid: "3",
ParentGuid: "4",
Text: "5",
AuthorSignature: "6",
}
var tests = []struct {
Order string
Expected string
}{
{
Order: "author parent_guid",
Expected: "1;4",
},
{
Order: "author parent_guid text guid",
Expected: "1;4;5;3",
},
{
Order: "",
Expected: "",
},
}
for i, test := range tests {
result := ExractSignatureText(test.Order, entity)
if strings.Join(result, ";") != test.Expected {
t.Errorf("#%d: Expected to be '%s', got '%s'", i, test.Expected, strings.Join(result, ";"))
}
}
}
......@@ -64,11 +64,7 @@ func SetLogger(writer LogWriter) {
}
func (l Logger) Info(values... interface{}) {
values = append(values, []interface{}{""})
copy(values[1:], values[0:])
values[0] = l.Prefix
values = append(values, LOG_C_RESET)
l.Println(values)
l.Println(l.Prefix, values, LOG_C_RESET)
}
func (l Logger) Error(values... interface{}) {
......
......@@ -24,8 +24,7 @@ import (
"strings"
)
func ParseDecryptedRequest(entityXML []byte) (entity Entity, err error) {
var message Message
func ParseDecryptedRequest(entityXML []byte) (message Message, entity Entity, err error) {
err = xml.Unmarshal(entityXML, &message)
if err != nil {
logger.Error(err)
......@@ -48,18 +47,21 @@ func ParseDecryptedRequest(entityXML []byte) (entity Entity, err error) {
return
}
message.Sig.KeyId = string(keyId)
logger.Info("Entity sender", message.Sig.KeyId)
data, err := base64.URLEncoding.DecodeString(message.Data.Data)
if err != nil {
logger.Error(err)
return
}
logger.Info("Entity raw", string(data))
entity.SignatureOrder, err = FetchEntityOrder(data)
if err != nil {
logger.Error(err)
return
}
logger.Info("Entity order", entity.SignatureOrder)
err = xml.Unmarshal(data, &entity)
if err != nil {
......@@ -69,7 +71,7 @@ func ParseDecryptedRequest(entityXML []byte) (entity Entity, err error) {
return
}
func ParseEncryptedRequest(wrapper AesWrapper, privKey *rsa.PrivateKey) (entity Entity, err error) {
func ParseEncryptedRequest(wrapper AesWrapper, privKey *rsa.PrivateKey) (message Message, entity Entity, err error) {
entityXML, err := wrapper.Decrypt(privKey)
if err != nil {
logger.Error(err)
......
......@@ -22,22 +22,23 @@ import "testing"
func TestParseDecryptedRequest(t *testing.T) {
var xml = []byte(`<?xml version="1.0" encoding="UTF-8"?><me:env xmlns:me="http://salmon-protocol.org/ns/magic-env"><me:data type="application/xml">PHN0YXR1c19tZXNzYWdlPgogIDxhdXRob3I-ZGlhc3BvcmFfMm5kQGxvY2FsaG9zdDozMDAxPC9hdXRob3I-CiAgPGd1aWQ-ZmUyZDJhODA1MzQ4MDEzNWQwOGY1Mjk2ZjJlNzQ0N2I8L2d1aWQ-CiAgPGNyZWF0ZWRfYXQ-MjAxNy0wNy0yNVQwOToyNDozM1o8L2NyZWF0ZWRfYXQ-CiAgPHByb3ZpZGVyX2Rpc3BsYXlfbmFtZS8-CiAgPHRleHQ-cGluZzwvdGV4dD4KICA8cHVibGljPmZhbHNlPC9wdWJsaWM-Cjwvc3RhdHVzX21lc3NhZ2U-</me:data><me:encoding>base64url</me:encoding><me:alg>RSA-SHA256</me:alg><me:sig key_id="ZGlhc3BvcmFfMm5kQGxvY2FsaG9zdDozMDAx">NbuD4kERZzXPFRORH4NOcr7EAij-dWKTCG0eBBGZObN3Aic0lMAZ_rLU7o6PLOH9Q6p6dyneYjUjSu07vtI5Jy_N2XQpKUni3fUWxfDNgfMo26XKmxdJ5S2Gp1ux1ToO3FY9RByTZw5HZRpOBAfRSgttTgiY5_Yu5D-BLcEm_94R6FMWRniQXrMAt8hU9qCNSuVQlUKtuuy8qJXu6Z21VhI9lAT7wIALlR9UwIgz0e6UG9S9sU95f_38co0ibD1KbQpBd8c_lu5vCVIqlEe_Fa_xYZupMLaU8De-wzoBpBgqR65mRtUQTu2jP-Qxa3aXrANHxweIbnYfpZ5QcNA50hfyVJJSolczDSlDljTunEmHmWNaS3J7waEQsIDFATPFy6H5leRPpSzebXYca4T-EiapPP-mn41Vs3VKIdUXOHus_HcTPWRVT-Vr-yt7byFYEanb5b5lQ_IHcI0oyqX7RrVJid6UsBtwxwkX0FSc1cZgLhBQUgxBsUh5MNte-WZJv_6c9rHyNsH3rn9YEZp431P9GCe8gNdLY9bFQ1pYS9BxOAS2enu3yVpWpWRechiR7D__HC4-Hw2MHfSSmBQTxq5oO01_efEHB8XxWF85XYNT6_icXf3ZsTxkURT9HlHapkFwL7TlO5gPUZZVJt9f6kn9HoGQ56MX2n46KdKKid8=</me:sig></me:env>`)
entity, err := ParseDecryptedRequest([]byte(""))
_, entity, err := ParseDecryptedRequest([]byte(""))
if err == nil {
t.Errorf("Expected to be an error, got nil")
}
entity, err = ParseDecryptedRequest([]byte("<broken></broken"))
_, entity, err = ParseDecryptedRequest([]byte("<broken></broken"))
if err == nil {
t.Errorf("Expected to be an error, got nil")
}
entity, err = ParseDecryptedRequest(xml)
message, entity, err := ParseDecryptedRequest(xml)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
parseRequest(t, entity)
parseEntityRequest(t, entity)
parseMessageRequest(t, message)
}
func TestParseEncryptedRequest(t *testing.T) {
......@@ -51,29 +52,30 @@ func TestParseEncryptedRequest(t *testing.T) {
t.Errorf("Some error occured while parsing: %v", err)
}
entity, err := ParseEncryptedRequest(wrapper, privKey)
message, entity, err := ParseEncryptedRequest(wrapper, privKey)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
parseRequest(t, entity)
parseEntityRequest(t, entity)
parseMessageRequest(t, message)
w := wrapper
w.AesKey = ""
_, err = ParseEncryptedRequest(w, privKey)
_, _, err = ParseEncryptedRequest(w, privKey)
if err == nil {
t.Errorf("Expected to be an error, got nil")
}
w = wrapper
w.MagicEnvelope = ""
_, err = ParseEncryptedRequest(w, privKey)
_, _, err = ParseEncryptedRequest(w, privKey)
if err == nil {
t.Errorf("Expected to be an error, got nil")
}
}
func parseRequest(t *testing.T, entity Entity) {
func parseEntityRequest(t *testing.T, entity Entity) {
// {XMLName:{Space: Local:} Type:status_message SignatureOrder:author guid created_at text public Data:{XMLName:{Space: Local:status_message} Author:diaspora_2nd@localhost:3001 Guid:fe2d2a8053480135d08f5296f2e7447b CreatedAt:2017-07-25 09:24:33 +0000 UTC ProviderName: Text:ping Photo:<nil> Location:<nil> Poll:<nil> Public:false Event:<nil>}}
if entity.Type != "status_message" {
t.Errorf("Expected type string 'status_message', got '%s'", entity.Type)
......@@ -87,3 +89,41 @@ func parseRequest(t *testing.T, entity Entity) {
t.Errorf("Expected the struct type EntityStatusMessage, got %+v", entity.Data)
}
}
func parseMessageRequest(t *testing.T, message Message) {
var data = `PHN0YXR1c19tZXNzYWdlPgogIDxhdXRob3I-ZGlhc3BvcmFfMm5kQGxvY2FsaG9zdDozMDAxPC9hdXRob3I-CiAgPGd1aWQ-ZmUyZDJhODA1MzQ4MDEzNWQwOGY1Mjk2ZjJlNzQ0N2I8L2d1aWQ-CiAgPGNyZWF0ZWRfYXQ-MjAxNy0wNy0yNVQwOToyNDozM1o8L2NyZWF0ZWRfYXQ-CiAgPHByb3ZpZGVyX2Rpc3BsYXlfbmFtZS8-CiAgPHRleHQ-cGluZzwvdGV4dD4KICA8cHVibGljPmZhbHNlPC9wdWJsaWM-Cjwvc3RhdHVzX21lc3NhZ2U-`
var sig = `NbuD4kERZzXPFRORH4NOcr7EAij-dWKTCG0eBBGZObN3Aic0lMAZ_rLU7o6PLOH9Q6p6dyneYjUjSu07vtI5Jy_N2XQpKUni3fUWxfDNgfMo26XKmxdJ5S2Gp1ux1ToO3FY9RByTZw5HZRpOBAfRSgttTgiY5_Yu5D-BLcEm_94R6FMWRniQXrMAt8hU9qCNSuVQlUKtuuy8qJXu6Z21VhI9lAT7wIALlR9UwIgz0e6UG9S9sU95f_38co0ibD1KbQpBd8c_lu5vCVIqlEe_Fa_xYZupMLaU8De-wzoBpBgqR65mRtUQTu2jP-Qxa3aXrANHxweIbnYfpZ5QcNA50hfyVJJSolczDSlDljTunEmHmWNaS3J7waEQsIDFATPFy6H5leRPpSzebXYca4T-EiapPP-mn41Vs3VKIdUXOHus_HcTPWRVT-Vr-yt7byFYEanb5b5lQ_IHcI0oyqX7RrVJid6UsBtwxwkX0FSc1cZgLhBQUgxBsUh5MNte-WZJv_6c9rHyNsH3rn9YEZp431P9GCe8gNdLY9bFQ1pYS9BxOAS2enu3yVpWpWRechiR7D__HC4-Hw2MHfSSmBQTxq5oO01_efEHB8XxWF85XYNT6_icXf3ZsTxkURT9HlHapkFwL7TlO5gPUZZVJt9f6kn9HoGQ56MX2n46KdKKid8=`
if message.Me != XMLNS_ME {
t.Errorf("Expected to be %s, got %s", XMLNS_ME, message.Me)
}
if message.Encoding != BASE64_URL {
t.Errorf("Expected to be %s, got %s", BASE64_URL, message.Encoding)
}
if message.Alg != RSA_SHA256 {
t.Errorf("Expected to be %s, got %s", RSA_SHA256, message.Alg)
}
if message.Data.Type != APPLICATION_XML {
t.Errorf("Expected to be %s, got %s", APPLICATION_XML, message.Data.Type)
}
if message.Data.Data != data {
t.Errorf("Expected to be %s, got %s", data, message.Data.Data)
}
if message.Sig.Sig != sig {
t.Errorf("Expected to be %s, got %s", sig, message.Sig.Sig)
}
if message.Sig.KeyId != TEST_AUTHOR {
t.Errorf("Expected to be %s, got %s", TEST_AUTHOR, message.Sig.KeyId)
}
if message.Signature() != `NbuD4kERZzXPFRORH4NOcr7EAij-dWKTCG0eBBGZObN3Aic0lMAZ_rLU7o6PLOH9Q6p6dyneYjUjSu07vtI5Jy_N2XQpKUni3fUWxfDNgfMo26XKmxdJ5S2Gp1ux1ToO3FY9RByTZw5HZRpOBAfRSgttTgiY5_Yu5D-BLcEm_94R6FMWRniQXrMAt8hU9qCNSuVQlUKtuuy8qJXu6Z21VhI9lAT7wIALlR9UwIgz0e6UG9S9sU95f_38co0ibD1KbQpBd8c_lu5vCVIqlEe_Fa_xYZupMLaU8De-wzoBpBgqR65mRtUQTu2jP-Qxa3aXrANHxweIbnYfpZ5QcNA50hfyVJJSolczDSlDljTunEmHmWNaS3J7waEQsIDFATPFy6H5leRPpSzebXYca4T-EiapPP-mn41Vs3VKIdUXOHus_HcTPWRVT-Vr-yt7byFYEanb5b5lQ_IHcI0oyqX7RrVJid6UsBtwxwkX0FSc1cZgLhBQUgxBsUh5MNte-WZJv_6c9rHyNsH3rn9YEZp431P9GCe8gNdLY9bFQ1pYS9BxOAS2enu3yVpWpWRechiR7D__HC4-Hw2MHfSSmBQTxq5oO01_efEHB8XxWF85XYNT6_icXf3ZsTxkURT9HlHapkFwL7TlO5gPUZZVJt9f6kn9HoGQ56MX2n46KdKKid8=` {
t.Errorf("Expected different signature, got '%s'", message.Signature())
}
}
......@@ -26,21 +26,22 @@ import (
"strings"
)
type signature interface {
SignatureText() []string
type SignatureInterface interface {
Signature() string
SignatureText(string) []string
}
type Signature struct {
entity SignatureInterface
delim string
signatureText []string
Err error
}
func (signature *Signature) New(sig signature) *Signature {
signature.signatureText = sig.SignatureText()
func (signature *Signature) New(entity SignatureInterface) *Signature {
signature.entity = entity
signature.delim = SignatureAuthorDelimiter
if _, ok := sig.(Message); ok {
if _, ok := entity.(Message); ok {
signature.delim = SignatureDelimiter
}
return signature
......@@ -48,7 +49,8 @@ func (signature *Signature) New(sig signature) *Signature {
func (signature *Signature) Sign(privKey *rsa.PrivateKey, sig *string) error {
h := sha256.New()
h.Write([]byte(strings.Join(signature.signatureText, signature.delim)))
h.Write([]byte(strings.Join(
signature.entity.SignatureText(""), signature.delim)))
digest := h.Sum(nil)
rng := rand.Reader
......@@ -61,9 +63,20 @@ func (signature *Signature) Sign(privKey *rsa.PrivateKey, sig *string) error {
return nil
}
func (signature *Signature) Verify(pubKey *rsa.PublicKey, sig []byte) bool {
message := []byte(strings.Join(signature.signatureText, signature.delim))
err := rsa.VerifyPKCS1v15(pubKey, crypto.SHA256, message[:], sig)
func (signature *Signature) Verify(order string, pubKey *rsa.PublicKey) bool {
sig, err := base64.StdEncoding.DecodeString(signature.entity.Signature())
if err != nil {
sig, err = base64.URLEncoding.DecodeString(signature.entity.Signature())
if err != nil {
signature.Err = err
return false
}
}
orderArr := signature.entity.SignatureText(order)
message := []byte(strings.Join(orderArr, signature.delim))
hashed := sha256.Sum256(message)
err = rsa.VerifyPKCS1v15(pubKey, crypto.SHA256, hashed[:], sig)
signature.Err = err
return err == nil
}
package federation
//
// GangGo Diaspora Federation Library
// Copyright (C) 2017 Lukas Matt <lukas@zauberstuhl.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
import (
"testing"
)
func TestSignatureInterface(t *testing.T) {
var signature Signature
var sig string
priv, err := ParseRSAPrivateKey(TEST_PRIV_KEY)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
err = signature.New(EntityLike{}).Sign(priv, &sig)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
if !signature.New(EntityLike{AuthorSignature: sig}).Verify(
"positive guid parent_guid parent_type author", &priv.PublicKey) {
t.Errorf("Expected to be a valid signature, got invalid")
}
err = signature.New(EntityComment{}).Sign(priv, &sig)
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
if !signature.New(EntityComment{AuthorSignature: sig}).Verify(
"author created_at guid parent_guid text", &priv.PublicKey) {
t.Errorf("Expected to be a valid signature, got invalid")
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment