// array and returns it.
 func parsePrintableString(bytes []byte) (ret string, err error) {
        for _, b := range bytes {
-               if !isPrintable(b) {
+               if !isPrintable(b, allowAsterisk) {
                        err = SyntaxError{"PrintableString contains invalid character"}
                        return
                }
        return
 }
 
+type asteriskFlag bool
+
+const (
+       allowAsterisk  asteriskFlag = true
+       rejectAsterisk asteriskFlag = false
+)
+
 // isPrintable reports whether the given b is in the ASN.1 PrintableString set.
-func isPrintable(b byte) bool {
+// If asterisk is allowAsterisk then '*' is also allowed, reflecting existing
+// practice.
+func isPrintable(b byte, asterisk asteriskFlag) bool {
        return 'a' <= b && b <= 'z' ||
                'A' <= b && b <= 'Z' ||
                '0' <= b && b <= '9' ||
                // This is technically not allowed in a PrintableString.
                // However, x509 certificates with wildcard strings don't
                // always use the correct string type so we permit it.
-               b == '*'
+               (bool(asterisk) && b == '*')
 }
 
 // IA5String
 
 
 func makePrintableString(s string) (e encoder, err error) {
        for i := 0; i < len(s); i++ {
-               if !isPrintable(s[i]) {
+               // The asterisk is often used in PrintableString, even though
+               // it is invalid. If a PrintableString was specifically
+               // requested then the asterisk is permitted by this code.
+               if !isPrintable(s[i], allowAsterisk) {
                        return nil, StructuralError{"PrintableString contains invalid character"}
                }
        }
                        // a PrintableString if the character set in the string is
                        // sufficiently limited, otherwise we'll use a UTF8String.
                        for _, r := range v.String() {
-                               if r >= utf8.RuneSelf || !isPrintable(byte(r)) {
+                               if r >= utf8.RuneSelf || !isPrintable(byte(r), rejectAsterisk) {
                                        if !utf8.ValidString(v.String()) {
                                                return nil, errors.New("asn1: string not valid UTF-8")
                                        }
 
        A string `asn1:"printable"`
 }
 
+type genericStringTest struct {
+       A string
+}
+
 type optionalRawValueTest struct {
        A RawValue `asn1:"optional"`
 }
        {optionalRawValueTest{}, "3000"},
        {printableStringTest{"test"}, "3006130474657374"},
        {printableStringTest{"test*"}, "30071305746573742a"},
+       {genericStringTest{"test"}, "3006130474657374"},
+       {genericStringTest{"test*"}, "30070c05746573742a"},
        {rawContentsStruct{nil, 64}, "3003020140"},
        {rawContentsStruct{[]byte{0x30, 3, 1, 2, 3}, 64}, "3003010203"},
        {RawValue{Tag: 1, Class: 2, IsCompound: false, Bytes: []byte{1, 2, 3}}, "8103010203"},